読者です 読者をやめる 読者になる 読者になる

woshidan's blog

そんなことよりコードにダイブ。

Androidのサンプルのコード読んでみた

思い立ったので眺めてみたけど、クラスに入っていた日付が2013年でちょっと古かったのでクラスの構成とかこういうこともできるんだ〜的な感じで眺めてました。

週1~2くらい適当に探して眺めると良いかも...。

クラス構成の話

f:id:woshidan:20151124012201p:plain

サンプル概要

RSSか何かのフィードからブログのタイトルを取得して、それを一覧で表示する。 ただし、高速化のため、最初に一度リクエストを投げてデータを取得した後、その結果をローカルのDBに保存して、その結果を利用する。 定期的に更新し直す*1

クラス構成

  • net
    • FeedParser
      • xmlをパースするためのクラス
  • provider
    • FeedContract
      • 認証用のデータやAPIのurl, パスなどの定数が入っているクラス
      • Contractは契約、約定といった意味
    • FeedProvider
      • 引数(それがネットから来ているのか、Activityで適当な初期値を渡しているのかこのクラスは知らない)を受け取って内部DBのデータを更新したり
      • SelectionBuilderというクラスを使ってクエリを作って内部DBからデータを引き出したりしている
      • DBのところはいまはRealmかな
  • EntryListActivity
    • ほとんど何も無い. fragmentの配置されたActivityのレイアウトからViewを作っているだけ
  • EntryListFragment
    • SyncUtilsクラスを使って、定期/ボタンを押したときに一覧表示用のデータを更新している
    • 一覧用のAdapterにAdapter#setViewBinderって見えて少しだけなるほど...となったような気がした
    • Loader周りのクラスやコールバックはいまはObservableに非同期処理を入れたRx周りを使うのかな
  • SyncAdapter
    • ネット上のどこかにリクエストを投げてリクエストを送っている
    • SyncServiceクラスのもつIBinderオブジェクトを通してonPerformSync()が呼び出される
    • HttpURLConnection周りでの実際の処理はprivate
    • 取得結果のstreamをマージしてるみたいだった
    • この辺のContentProviderを通してつっこんでいるあたりのイベントは SyncStatusObserver で見るのかな...?
  • SyncService
    • とりあえずSyncAdapterに対してSingletonをやるためのラッパーではある
    • IBinderってだあれ...
  • SyncUtils
    • 窓口となっているクラス。ViewのクラスからはSyncUtilsのstaticメソッドとして通信してデータ取得を行う

レイアウトの話

<!-- activit_entry_list.xml -->
<!-- Activityのレイアウトにfragmentを置くとき、LayoutクラスのViewGroupで包まなくてもいいのか -->
<?xml version="1.0" encoding="utf-8"?>

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:id="@+id/entry_list"
          android:name="com.example.android.basicsyncadapter.EntryListFragment"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:layout_marginLeft="16dp"
          android:layout_marginRight="16dp"
          tools:context=".EntryListActivity"
          tools:layout="@android:layout/list_content" />
// EntryListFragment
// inflater.inflate(R.menu.main, menu); menuのリソースからViewを作る
    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        mOptionsMenu = menu;
        inflater.inflate(R.menu.main, menu);
    }

// menuのボタンを押して一時的に処理中という表示をするために
// menuのボタンの部分に入るレイアウトを下記にものにしている
// itemのidで指定して動的にmenuのボタンのアイコンって変えられるんだねぇ
    final MenuItem refreshItem = mOptionsMenu.findItem(R.id.menu_refresh);
    if (refreshItem != null) {
        if (refreshing) {
            refreshItem.setActionView(R.layout.actionbar_indeterminate_progress);
        } else {
            refreshItem.setActionView(null);
        }
    }
<!-- actionbar_indeterminate_progress.xml -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_height="wrap_content"
             android:layout_width="@dimen/action_button_min_width"
             android:minWidth="@dimen/action_button_min_width">

    <ProgressBar android:layout_width="@dimen/indeterminate_progress_size"
                 android:layout_height="@dimen/indeterminate_progress_size"
                 android:layout_gravity="center"
                 style="?indeterminateProgressStyle" />
</FrameLayout>

*1:アプリを開いている間は?