web-dev-qa-db-ja.com

LoaderManager.restartLoader()は常にonCreateLoader()の呼び出しになりますか?

LoaderManagerにはこのメソッドがあります restartLoader()

public abstract Loader<D> restartLoader (int id, Bundle args, LoaderCallbacks<D> callback)

このマネージャーで新しいローダーを開始するか、既存のローダーを再起動し、それにコールバックを登録して、(アクティビティ/フラグメントが現在開始されている場合)ロードを開始します。同じIDのローダーが以前に開始されている場合、新しいローダーが作業を完了すると、ローダーは自動的に破棄されます。コールバックは、古いローダーが破棄される前に配信されます。

開発ガイド に基づいて、実際、onCreateLoaderの呼び出しは常にrestartLoader()から生じると思います。

ローダーの再起動

.。

古いデータを破棄するには、restartLoader()を使用します。たとえば、このSearchView.OnQueryTextListenerの実装は、ユーザーのクエリが変更されたときにローダーを再起動します。ローダーを再起動して、改訂された検索フィルターを使用して新しいクエリを実行できるようにする必要があります。

public boolean onQueryTextChanged(String newText) {
    // Called when the action bar search text has changed.  Update
    // the search filter, and restart the loader to do a new query
    // with this filter.
    mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
    getLoaderManager().restartLoader(0, null, this);
    return true;
}

public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    // NOTE: The Loader is instantiated with the user's query

    Uri baseUri;       
    if (mCurFilter != null) {
        baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                  Uri.encode(mCurFilter));
    } else {
        baseUri = Contacts.CONTENT_URI;
    }

    // Now create and return a CursorLoader that will take care of
    // creating a Cursor for the data being displayed.
    String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
            + Contacts.HAS_PHONE_NUMBER + "=1) AND ("
            + Contacts.DISPLAY_NAME + " != '' ))";
    return new CursorLoader(getActivity(), baseUri,
            CONTACTS_SUMMARY_PROJECTION, select, null,
            Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
}

この例では、onCreateLoaderは、ユーザーのクエリに関する情報が(インスタンス化時に)ローダーに渡される唯一の場所です。ただし、ドキュメントでは、「新しいローダーを開始するまたは既存のローダーを再起動する」と言って、私を失望させます。

15
Maarten

あなたの質問に対する簡単な答えは「はい」です。restartLoader()を呼び出すと、onCreateLoader()が再度呼び出されます。

複数のローダーを並行して開始できます(たとえば、2つのSimpleCursorAdapterを入力する必要があります)。例:

getLoaderManager().initLoader(0, null, this);  //id = 0
getLoaderManager().initLoader(1, null, this);  //id = 1

次に、onCreateLoaderは、IDごとにローダーマネージャーによって呼び出されます(返されるローダーは、ローダーマネージャーによって非同期に構築されます)。

public Loader<Cursor> onCreateLoader(int id, Bundle args)
{
    if (id == 0)
        //return a Loader<Cursor> for id 0
    else if (id == 1)
        //return a Loader<Cursor> for id 1
}

ローダーマネージャーは、結果のローダーをonLoadFinishedに渡します。

public void onLoadFinished(Loader<Cursor> loader, Cursor cursor)
{
    if (loader.getId() == 0)
        //cursor was returned from onCreateLoader for id 0
        //perhaps do swapCursor(cursor) on an adapter using this loader
    else if (loader.getId() == 1)
        //cursor was returned from onCreateLoader for id 1
        //perhaps do swapCursor(cursor) on an adapter using this loader
}

その後、リスタートローダーを呼び出すと:

getLoaderManager().restartLoader(0, null, this);  //id = 0

... onLoaderResetが最初に呼び出されます。

public void onLoaderReset(Loader<Cursor> loader)
{
    if (loader.getId() == 0)
        //perhaps do swapCursor(null) on an adapter using this loader
    else if (loader.getId() == 1)
        //perhaps do swapCursor(null) on an adapter using this loader
}

...その後にonCreateLoaderへの新しい呼び出しが続きます。したがって、その点で、onCreateLoaderは、新しいローダーを開始するときと、既存のローダーがリセットされるときの両方に使用されます。

29
NigelK