2014-01-21 4 views
12

LoaderManagerこの方法restartLoader()ありますLoaderManager.restartLoader()は常にonCreateLoader()を呼び出しますか?

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

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

the dev guideに基づいて、私は確かに、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は、ユーザーのクエリに関する情報はローダに渡される唯一の場所である、:それは新しいクエリを実行するために改訂された検索フィルタを使用できるように、ローダーを再起動する必要があります(インスタンス化時)。しかし、ドキュメントでは、「新しいを起動するか、既存のローダーを再起動する」と言って、私を捨てます。

答えて

24

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

あなたは例えば、(あなたが埋めるために2 SimpleCursorAdaptersを持っていると言う)に並列に複数のローダーを起動することができます。

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

onCreateLoaderは、各IDのローダマネージャによって呼び出される(返されるローダがありますその後、)ローダManagerによって非同期的に構築された:

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 
} 

ローダーManagerは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は、新しいローダの起動と、既存のローダのリセットの両方に使用されます。

+0

私は 'onCreateLoader'もUIスレッドで呼び出されていると思います...! – Maarten

+0

私はあなたがそうであると思う理由について興味がありますか?これは、ContentProvider/Datasourceと非同期でやりとりするためのローダー全体のポイントです。UIをブロックする可能性がある長期実行タスクは、onCreateLoaderで実行されます.LoaderManagerはその部分をバックグラウンドで実行します。 – NigelK

+0

はい、はい、AsyncTaskLoaderの['loadInBackBackground'](https://developer.android.com/reference/android/content/AsyncTaskLoader.html)部分は確実にバックグラウンドスレッドで実行されますが、onCreateLoaderはUIスレッド:[ローダーのクライアントは、プロセスのメインスレッド(つまり、アクティビティのコールバックや他のことが発生しているスレッド)からローダーへの呼び出しを実行する必要があります。](https://developer.android AsyncTask'のインスタンス化に匹敵する、それは私の推論でした。 – Maarten

関連する問題