LoaderManager使用詳解(二)---瞭解LoaderManager

來源:互聯網
上載者:User

瞭解LoaderManager
這篇文章將介紹LoaderManager類,這是該系列的第二篇文章。一:Loaders之前世界二:瞭解LoaderManager三:實現Loaders四:執行個體:AppListLoader
注意:要瞭解這一LoaderManager這部分知識,要求對Loaders如何工作有基本瞭解。Loaders的實現將在下一篇文章中涵蓋。現在你只需要將Loaders看成一個簡單、字包含的對象。該對象特性包括:1.在一個單獨線程載入資料;2.監測底層資料來源,當探測到有改變時就更新或者重新查詢。瞭解上面的Loader相關內容就足以瞭解本文內容了。下文所有的Loaders假設100%正確。
LoaderManager是什嗎?
簡單的理解是,LoaderManager用來負責管理與Activity或者Fragment聯絡起來的一個或多個Loaders對象。每個Activity或者Fragment都有唯一的一個LoaderManager執行個體,用來啟動、停止、保持、重啟、關閉它的Loaders。這些事件有時直接在用戶端通過調用initLoader()/restartLoader()/destroyLoader()函數來實現。通常這些事件通過主要的Activity/Fragment聲明周期事件來觸發,而不是手動(當然也可以手動調用)。比如,當一個Activity關閉時(destroyed),改活動將指示它的LoaderManager來銷毀並且關閉它的Loaders(當然也會銷毀並關閉與這些Loaders關聯的資源,比如Cursor)。LoaderManager並不知道資料如何裝載以及何時需要裝載。相反地,LoaderManager只需要控制它的Loaders們開始、停止、重設他們的Load行為,在配置變換(比如橫豎屏切換)時保持loaders們的狀態,並提供一個簡單的介面來擷取load結果到用戶端中。從上面的行為可以看到,LoaderManager是一個比現在過時的startManagingCursor方法更加智能和通用的方法。在Activity的聲明周期狀態輪轉中,比較兩種管理資料的方法,可以發現LoaderManager方法有下面幾個方面更勝一籌:
1. startManagingCursor管理Cursors,而LoaderManager管理Loader<D>對象。Loader<D>是一個模板類,D是一個包含了需要載入資料的類。也就是說,資料來源並不必須是Cursor,它可以是List、JSONArray。。。任何類。LoaderManager與它包含的資料內容解耦了,所以更加靈活。
2. 調用startManagingCursor會導致Activity在已經加入管理的Cursor上調用requery()方法。在第一篇文章中提到過,在UI線程執行requery()方法代價非常高。相反的是,Loader<D>的子類會非同步載入(譯者註:另外再開一個線程,就叫非同步了。)資料,所以使用LoaderManager永遠不會產生阻塞UI線程的情況。
3. startManagingCursor在配置變化(例如橫豎屏切換)時,並不會保持Cursor的狀態。麻煩的是,每次Activity由於配置變化(比如,簡單的橫豎屏切換),都會導致Cursor下回並且被重新查詢。LoaderManager就智能多了,當配置變化時,它會保持它裡面的Loader們的狀態,所以並不需要重新查詢資料。
4. LoaderManager提供無縫的資料監測。任何時候,當Loader的資料來源改變,LoaderManager將會從對應的Loader上面接收到一個新的同步載入資料,並將更新資料返回給用戶端(注意:僅當Loader被正確實現,LoaderManager才會接收到這些資料變化通知。我們將會在該系列的第三篇文章討論自訂Loaders的實現)。
如果你覺得上面很難,我也並不會強調她。上面的內容最重要的是LoaderManager讓你的生活更容易。LoaderManager為你初始化、管理、銷毀Loaders,減少了代碼複雜度和與Activity或者Fragment生命週期相關的bug。更多地,與LoaderManager互動需要實現三個簡單的回調方法,我們在下一節將討論LoaderManager.LoaderCallbacks<D>。
實現LoaderManager.LoaderCallbacks<D>介面LoaderManager.LoaderCallbacks<D>介面LoaderManager用來向客戶返回資料的方式。每個Loader都有自己的回調對象供與LoaderManager進行互動。該回調對象在實現LoaderManager中地位很高,告訴LoaderManager如何執行個體化Loader(onCreateLoader),以及當載入行為結束或者重啟(onLoadFinished或者onLoadReset)之後執行什麼操作。大多數情況,你需要把該介面實現為組件的一部分,比如說讓你的Activity或者Fragment實現LoadManager.LoaderCallbacks<D>介面。

public class SampleActivity extends Activity implements LoaderManager.LoaderCallbacks<D> {  public Loader<D> onCreateLoader(int id, Bundle args) { ... }  public void onLoadFinished(Loader<D> loader, D data) { ... }  public void onLoaderReset(Loader<D> loader) { ... }  /* ... */}

一旦實現該介面,用戶端將回調對象(本例中為“this”)作為LoaderManager的initLoader函數的第三個參數傳輸。總的來說,實現回調介面非常直接明了。每個回調方法都有各自明確的與LoaderManager進行互動的目的:1. onCreateLoader是一個Factory 方法,用來返回一個新的Loader。LoaderManager將會在它第一次建立Loader的時候調用該方法。2. onLoadFinished方法將在Loader建立完畢的時候自動調用。典型用法是,當載入資料完畢,用戶端(譯者註:調用它的Activity之類的)需要更新應用UI。用戶端假設每次有新資料的時候,新資料都會返回到這個方法中。記住,檢測資料來源是Loader的工作,Loader也會執行實際的同步載入操作。一旦Loader載入資料完成,LoaderManager將會接受到這些載入資料,並且將將結果傳給回調對象的onLoadFinished方法,這樣用戶端(比如Activity或者Fragment)就能使用該資料了。
3. 最後,當Loader們的資料被重設的時候將會調用onLoadReset。該方法讓你可以從就的資料中移除不再有用的資料。
在下一節中,我們將討論Android初學者們經常問到的問題:如何從過時的Managed Cursor轉移到更強大的LoaderManager來?
從Managed Cursor轉移到LoaderManager下面的代碼跟上一篇文章的代碼實現的功能類似。當然,不同就是改成使用LoaderManager來實現。CursorLoader確保所有的查詢都是非同步執行,這確保了我們不會阻塞UI線程。更進一步,LoaderManager在Activity全生命週期管理CursorLoader,當配置轉換時保持它的資料。處理每次新資料在回調介面的onLoadFinished方法中的載入。這樣Activity可以很自由的使用查詢結果。
public class SampleListActivity extends ListActivity implements    LoaderManager.LoaderCallbacks<Cursor> {  private static final String[] PROJECTION = new String[] { "_id", "text_column" };  // The loader's unique id. Loader ids are specific to the Activity or  // Fragment in which they reside.  private static final int LOADER_ID = 1;  // The callbacks through which we will interact with the LoaderManager.  private LoaderManager.LoaderCallbacks<Cursor> mCallbacks;  // The adapter that binds our data to the ListView  private SimpleCursorAdapter mAdapter;  @Override  public void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    String[] dataColumns = { "text_column" };    int[] viewIDs = { R.id.text_view };    // Initialize the adapter. Note that we pass a 'null' Cursor as the    // third argument. We will pass the adapter a Cursor only when the    // data has finished loading for the first time (i.e. when the    // LoaderManager delivers the data to onLoadFinished). Also note    // that we have passed the '0' flag as the last argument. This    // prevents the adapter from registering a ContentObserver for the    // Cursor (the CursorLoader will do this for us!).    mAdapter = new SimpleCursorAdapter(this, R.layout.list_item,        null, dataColumns, viewIDs, 0);    // Associate the (now empty) adapter with the ListView.    setListAdapter(mAdapter);    // The Activity (which implements the LoaderCallbacks<Cursor>    // interface) is the callbacks object through which we will interact    // with the LoaderManager. The LoaderManager uses this object to    // instantiate the Loader and to notify the client when data is made    // available/unavailable.    mCallbacks = this;    // Initialize the Loader with id '1' and callbacks 'mCallbacks'.    // If the loader doesn't already exist, one is created. Otherwise,    // the already created Loader is reused. In either case, the    // LoaderManager will manage the Loader across the Activity/Fragment    // lifecycle, will receive any new loads once they have completed,    // and will report this new data back to the 'mCallbacks' object.    LoaderManager lm = getLoaderManager();    lm.initLoader(LOADER_ID, null, mCallbacks);  }  @Override  public Loader<Cursor> onCreateLoader(int id, Bundle args) {    // Create a new CursorLoader with the following query parameters.    return new CursorLoader(SampleListActivity.this, CONTENT_URI,        PROJECTION, null, null, null);  }  @Override  public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {    // A switch-case is useful when dealing with multiple Loaders/IDs    switch (loader.getId()) {      case LOADER_ID:        // The asynchronous load is complete and the data        // is now available for use. Only now can we associate        // the queried Cursor with the SimpleCursorAdapter.        mAdapter.swapCursor(cursor);        break;    }    // The listview now displays the queried data.  }  @Override  public void onLoaderReset(Loader<Cursor> loader) {    // For whatever reason, the Loader's data is now unavailable.    // Remove any references to the old data by replacing it with    // a null Cursor.    mAdapter.swapCursor(null);  }}

總結正如其名LoaderManager,它負責在Activity或者Fragment的生命週期內管理Loader們。LoaderManager很簡單,並且它的實現代碼量通常很少。比較難的部分是實現Loaders,這個主題將在下一篇文章中討論:實現Loaders(三)(超連結)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.