web-dev-qa-db-ja.com

LoaderManagerを備えたCursorLoaderは、カーソルをCursorAdapterに送信することをどのように認識しますか?

コードの一部を調べていたところ、CursorLoaderLoaderManagerの組み合わせをCursorAdapter接続でどのように使用するかが実際にはわからないことに気付きました。これが私が混乱している部分です。

_agendaAdapter = new MyAgendaAdapter(this, null);

makeProviderBundle(new String[] {"_id", "event_name", "start_date", "start_time",
    "end_date", "end_time", "location"}, "date(?) >= start_date and date(?) <= end_date", 
new String[]{getChosenDate(), getChosenDate()}, null);

getLoaderManager().initLoader(0, myBundle, MainDisplayActivity.this);
list.setAdapter(agendaAdapter);
_

では、カスタムContentProviderquery()メソッドは、それをその特定のCursorAdapterに送信することをどのように知っているのでしょうか?接続が表示されません。私はその中の他のすべてを理解していますが、この質問は何ですか。ああ、私が言及する必要があります、コードは正常に動作します。

22
Andy

まず、 この投稿 および この投稿 のコードサンプルをチェックして、プロセスがどのように機能するかをさらに詳しく調べてください。

そして今、あなたの質問に答えるために...

カスタムContentProvider...のquery()メソッドはどのようになっていますか?

まず、getContentResolver().query()はコンテンツプロバイダーのqueryメソッドを直接呼び出さないことを覚えておいてください。 Uriを解析し、呼び出すプロバイダーを決定し、次にプロバイダーのqueryを呼び出すコンテンツリゾルバーのクエリメソッドを呼び出しています。メソッド

クエリはどのようにしてその特定のCursorAdapterに送信されますか?

例として APIデモ を使用してプロセスを説明します。 APIデモでは、ListFragmentの代わりにListActivityを使用することに注意してください(この質問のコンテキストでは、違いは重要ではありません)。


  1. まず、CursorAdapterを作成(および設定)します。

    _mAdapter = new SimpleCursorAdapter(
            getActivity(),
            Android.R.layout.simple_list_item_2, 
            null,
            new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
            new int[] { Android.R.id.text1, Android.R.id.text2 }, 
            0);
    _

    このステートメントが実行された後、SimpleCursorAdapterは、カーソルデータをビューに関連付ける方法を認識します。カーソルの_Contacts.DISPLAY_NAME_列にあるデータはすべて、ID _Android.R.id.text1_などのビューに関連付けられます。

    コンストラクターの3番目の引数としてnullカーソルを渡したことに注意してください。これは非常に重要です。まだデータを照会していないためです(これはLoaderManagerCursorLoaderの仕事です)。

  2. 次に、ローダーを初期化します。

    _getLoaderManager().initLoader(0, null, this);
    _

    これは、ID _0_に対応するLoaderManagerを作成して開始するようにLoaderに指示します。

  3. LoaderManageronCreateLoader(int id, Bundle args)を呼び出します。

    onCreateloaderは、_Loader<Cursor>_インターフェースのサブクラス(つまり、この場合はCursorLoader)を返します。このCursorLoaderは最初のクエリを実行し、データが変更されると自動的に更新されます。

    アクティビティ/フラグメントに複数のローダーがある場合は、switch(id)を使用して、読み込みプロセスを開始するように指示された特定のローダーを判別します。

  4. 照会されたカーソルはonLoadFinished()に渡されます。

    ステップ3でCursorLoaderがインスタンス化されて返されるとすぐに、CursorLoaderは別のスレッドで初期クエリを実行し、カーソルが返されます。 CursorLoaderがクエリを終了すると、新しくクエリされたカーソルがLoaderManagerに返され、onLoadFinishedメソッドにカーソルが渡されます。ドキュメントによると、「以前に作成されたローダーがロードを終了すると、onLoadFinishedメソッドが呼び出されます。」

  5. クエリされたデータはCursorAdapterに関連付けられています。

    _mAdapter.swapCursor(data);
    _

    onLoadFinishedは通常、クエリされたデータでアクティビティ/フラグメントのUIを更新する場所でもあることに注意してください。以前にsetListAdapter(mAdapter)を呼び出したので、この場合、これは必要ありません。 ListFragmentCursorAdapterの使用方法を知っています(ステップ1を参照)...必要なのは、アダプターにswapCursorListFragmentが画面にデータを表示します。

ご不明な点がございましたら(またはタイプミスなどがありましたら)お知らせください。


TL; DR

クエリされたデータを含むカーソルは、CursorAdapteronLoadFinishedに関連付けられています。これは通常、mAdapter.swapCursor(data)を呼び出すことによって行われます。

84
Alex Lockwood