2012/02/23

LoaderのAPIまとめ

■Loaderの概要
  • 非同期のデータロードを行うための雛形を提供します。
  • Loaderは、アクティブの間は対象となるデータセットソースを監視し、変更があった場
    合にクライアントへ通知を行います。


Loaderは非同期のデータロードを実行するための抽象クラスで、独自に拡張することが可
能ですが、直接Loaderクラスを継承することは推奨されていません。
代わりに、Loaderを継承したAsyncTaskLoaderを継承することができます。
AsyncTaskLoaderを継承した一般的な具象クラスはCursorをデータセットに持つCursorLoaderです。

参考:
 Loaderを継承した簡単なサンプル
 http://developer.android.com/intl/ja/resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderCustom.html

注意:Loaderを使用するクライアントは、Loaderを使用する際にはメインスレッドからコールする
必要があります。
例えば、AsyncTaskLoaderはロード処理をバックグラウンドスレッドで行いますが、ローダ
の呼び出しや、結果の受信スレッドはメインスレッドである必要があります。


■Loaderの主なメソッド群

●startLoading()
  • Loaderを開始します。
  • LoaderManager経由でLoaderを管理している場合、関連するActivity/Fragmentが開始さ
    れる時(onStart)、このメソッドはLoaderManagerによって自動的に呼び出されます。
  • 結果のロードが完了し、通知の準備ができればメインスレッドのコールバック
    (Loader.onLoadComplete)が呼び出されます。
    ただし、前回のロードが完了済みかつ有効である場合は即コールバックが呼び出されます。
    コールバック通知はstopLoadingを呼び出すことで一時停止することができます。
  • Loaderはデータセットソースに対するObserver(ForceLoadContentObserver)を内包しており、
    データセットソースの変更検知もLoaderが行ってくれます。
    そのため、Loaderを使用する場合はデータの監視を自身で行う必要はありませんが、
    CursorAdapterとLoaderを併用する場合には注意が必要で、
    CursorAdapter(android.content.Context, android.database.Cursor, int)コンストラ
    クタのflagには0をセットし、FLAG_AUTO_REQUERYまたはFLAG_REGISTER_CONTENT_OBSERVER
    はOFFしない(コンテンツ監視しない)ようにする必要があります。
  • startLoadingを呼び出すと、Loaderの内部状態が更新されます。
    具体的には 開始状態=true / リセット状態=false / abandon状態=false
    となります。(それぞれの状態はisStarted(), isReset(), isAbandoned()で取得可)
    startLoadingは状態更新後、サブクラスレスポンスのためにonStartLoading()をコールします。
  • このメソッドを直接コールするとLoaderの管理に影響がでるため避けるべきです。
  • このメソッドは常にメインスレッドから実行する必要があります。



●onStartLoading()
  • サブクラスはLoader開始時の実装をここで行います。
  • このメソッドはstartLoading()経由でコールされることが前提となります。
    クライアントが直接このメソッドをコールすることは推奨されません。
  • このメソッドは常にメインスレッドから実行する必要があります。



●stopLoading()
  • Loaderを停止し、startLoading()が呼ばれるまでデータの更新通知も停止します。
  • LoaderManager経由でLoaderを管理している場合、関連するActivity/Fragmentが停止
    される時、このメソッドはLoaderManagerによって自動的に呼び出されます。
  • 実装においては、この時点でデータセットを無効にするべきではありません。
    クライアントはLoaderが最後に通知したデータ結果を自由に使用できるようにするべき
    です。
  • Loaderが停止している間は、データセットが更新されてもそれがクライアントに通知さ
    れることはありません。
    ただし、Loaderが再開された時に正しい値(takeContentChangedの戻り値)を保証するた
    めに、データセットの監視は続けられます。
  • stopLoadingを呼び出すことで、Loaderの内部状態が更新されます。
    具体的には 開始状態=false となります。(それぞれの状態はisStarted()で取得可)
    stopLoadingは状態更新後、サブクラスレスポンスのためにonStopLoading()をコールします。
  • このメソッドを直接コールするとLoaderの管理に影響がでるため避けるべきです。
  • このメソッドは常にメインスレッドから実行する必要があります。



●onStopLoading()  
  • サブクラスはLoader停止要求時の実装をここで行います。
  • このメソッドはstopLoading()経由でコールされることが前提となります。
    クライアントが直接このメソッドをコールすることは推奨されません。
  • このメソッドは常にメインスレッドから実行する必要があります。



●abandon()
  • LoaderManager経由でLoaderを再起動(restartLoader)した際にLoaderManagerから自動的
    にコールされるメソッドです。
  • abandonはreset()の前にコールされます。
    Loaderはabandon状態になっても現在のデータを保持し続けますが、それが更新された
    としてもユーザに通知することはありません。
  • abandonを呼び出すことで、Loaderの内部状態が更新されます。
    具体的には abandon状態=true となります。(それぞれの状態はisAbandon()で取得可)
    abandonは状態更新後、サブクラスレスポンスのためにonAbandon()をコールします。
  • このメソッドを直接コールするとLoaderの管理に影響がでるため避けるべきです。



●onAbandon()
  • サブクラスはLoaderが不要となった時の実装をここで行います。
  • Abandon状態はLoaderが不要となった状態を指します。
    リセットされる時はonResetが呼ばれる為、onAbandonがコールされたときのLoaderは
    start→resetの中間的な状態であると言えます。
  • Abandon状態であるLoaderにクライアントは興味を持つことがありません。
    (おそらくクライアントは既に新しいLoaderを扱っています)
    そのため、AbandonなLoaderはユーザに通知を送ってはいけません。
    しかし、Loader.onReset()が処理されるまでLoaderはユーザに通知したデータを有効な
    状態に保ち続ける必要があります。
  • このメソッドはabandon()経由でコールされることが前提となります。
    クライアントが直接このメソッドをコールすることは推奨されません。
  • LoaderがAbandon状態かどうかはisAbandonedで取得可能です。



●reset()
  • このメソッドはLoaderを破棄する場合にLoaderManagerから自動的に呼ばれるメソッド
    です。resetによりLoaderは破棄されます。
  • このメソッドが再度コールされることはありません。
    Loaderはこの時点で解放できる全てのリソースを解放する必要があります。
    しかし、resetの後でstartLoadingが呼ばれることもあり、その際には再び実行可能で
    ある必要があります。
  • resetを呼び出すことで、Loaderの内部状態が更新されます。
    具体的には 開始状態=false / リセット状態=true / abandon状態=false /
    データソース変更状態=false となります。
    (それぞれの状態はisStarted(), isReset(), isAbandoned(), takeContentChanged()で
    取得可)
  • resetはLoaderの状態更新前に、サブクラスレスポンスの為にonReset()をコールします。
  • このメソッドを直接コールするとLoaderの管理に影響がでるため避けるべきです。
  • このメソッドは常にメインスレッドから実行する必要があります。



●onReset() 
  • サブクラスはLoaderのリセット要求時の実装をここで行います。
  • このメソッドはreset()経由でコールされることが前提となります。
    クライアントが直接このメソッドをコールすることは推奨されません。
  • このメソッドは常にメインスレッドから実行する必要があります。



●forceLoad()
  • Loaderによるロードを強制します。
  • startLoading()とは異なり、以前にロードしたデータは全てキャンセルされて、
    新しいものに置き換えられます。
  • forceLoadは、サブクラスレスポンスのためにonForceLoad()をコールします。
  • 通常、Loaderが開始状態(isStarted)の場合にこれを呼び出すべきです。
  • このメソッドは常にメインスレッドから実行する必要があります。



●onForceLoad()
  • サブクラスは強制ロード要求時の実装をここで行います。
  • このメソッドは常にメインスレッドから実行する必要があります。



●onContentChanged()
  • ForceLoadContentObserverがデータセットソースの変更を検知したときにコールされる
    メソッドです(ContentObserver.onChangeに相当)
  • デフォルトでは、Loaderが開始済みの場合にforceLoadをコールし、開始していない場合
    はtakeContentChangedがtrueを返すようにフラグを設定します。
  • このメソッドは常にメインスレッドから実行する必要があります。



●takeContentChanged() 
  • Loaderの停止中にデータセットに変更があったかどうかを取得できます。
    変更があった場合はtrueが返され、フラグ(変更状態)はリセットされます。



●deliverResult()
  • クライアントへロード結果を送信します。
  • このメソッドはサブクラスからコールされることを想定しており、この処理はメインス
    レッド上で実行する必要があります。



●isStarted()
  • Loaderが開始状態かどうかを返します。
  • Trueである場合はstartLoadingが呼び出されており、まだstopLoadingまたはresetが
    コールされていない状態であることを意味します。



●isAbandoned()
  • このLoaderが不要となったかどうかを返します。
  • abandon状態のLoaderは現在のデータを保持しますが、それが更新されたとしてもユーザ
    に通知しません。



●isReset()
  • Loaderがリセット状態かどうかを返します。
  • Trueである場合はLoaderがまだ1度も開始されていない状態、またはresetが既にコー
    ルされている状態などがあります。


以上です。