AsyncTaskLoader用法

關於Loader的基礎介紹能夠參考:http://www.javashuo.com/article/p-wxdvtxrv-hb.htmljava

本章主要經過一個簡單的例子闡述AsyncTaskLoader的用法和注意事項。git

1. AsyncTaskLoader簡介

AsyncTaskLoader是Loader的子類,其內部經過AsyncTask實現數據異步加載。github

2. AsyncTaskLoader用法

步驟一:建立一個Loader類繼承AsyncTaskLoader,並實現其相關抽象方法。好比:app

  • onStartLoading:註冊一些監聽器到loader上,而且執行一次forceLoad(); 不然loader不會開始工做。若是建立loader時不須要它馬上工做能夠不用調用forceLoader。
  • loadInBackground:不用說,在這裏就是加載數據而且返回,其實這個數據就返回到了LoaderManager的onLoadFinished方法第二個參數 
  • onStopLoading:中止加載數據,但不要中止監聽也不要釋放數據,就能夠隨時重啓loader 
  • onReset:先確保已經中止加載數據了,而後釋放掉監聽器並設爲null 
  • onCanceled: 在這裏能夠釋放資源,若是是list就不須要作什麼了,可是象cursor或者打開了什麼文件就應該關閉一下;
  • deliverResult:分發數據。

步驟二:獲取LoaderMananger:異步

LoaderMananger mananger = getSupportLoaderManager();

步驟三:建立LoaderMananger.LoaderCallbacks回調ide

LoaderManager.LoaderCallbacks callbacks = new LoaderManager.LoaderCallbacks() {
            @Override
            public Loader onCreateLoader(int id, Bundle args) {
                Logger.d("onCreateLoader");
                NewsLoader loader = new NewsLoader(LoaderActivity.this, mRepository);
                return loader;
            }

            @Override
            public void onLoadFinished(Loader loader, List<News> data) {
                for (News news : data) {
                    Logger.d("onLoadFinished title:" + news.getTitle()
                            + " desc:" + news.getDesc());
                }
            }

            @Override
            public void onLoaderReset(Loader loader) {
                Logger.d("onLoaderReset");
            }
        };

步驟四:初始化Loader測試

mNewsLoader = (NewsLoader) mLoaderMananger.initLoader(LOADER_ID, null, callbacks);

步驟五:啓動Loaderthis

mNewsLoader.forceLoad();

步驟六:Loader的其餘操做spa

mNewsLoader.startLoading();
mNewsLoader.stopLoading();
mNewsLoader.reset();
mNewsLoader.cancelLoad();

mLoaderMananger.restartLoader();
mLoaderMananger.destroyLoader();

步驟七:咱們能夠在數據源中添加監聽接口,在Loader中實現該接口,在該接口中觸發某些動做,好比forceLoad或deliveResult。.net

3. AsyncTaskLoader中的比較重要的方法調用流

  • LoaderMananger.initLoader() -> LoaderCallback.onCreateLoader() -> AsyncTaskLoader.onStartLoading()
  • AsyncTaskLoader.forceLoad() -> AsyncTaskLoader.loadInBackground() -> AsyncTaskLoader.deliverResult() -> OnLoadCompleteListener.onLoadComplete() -> LoadCallback.onLoadFinish()
  • AsyncTaskLoader.deliverResult() -> OnLoadCompleteListener.onLoadComplete() -> LoadCallback.onLoadFinish()

在更新數據的時候,咱們能夠調用forceLoad,這樣就會從loadInBackground方法中獲取數據;也能夠直接調用deliverResult,將數據傳入。

這兩種方法能夠用在不一樣的場景。好比forceLoad,適合在loadInBackground中有接口獲取數據的狀況下;deliverResult則適合在前面提到的步驟七,若是數據有更新,觸發了回調,咱們能夠在回調中deliveResult將數據傳入。

還有一點很是重要,前面兩種方法不論哪一種都會走到deliverResult,傳入deliverResult的對象必須是新建的。

LoaderMananger中有個LoaderInfo類,它是OnLoadCompleteListener的實現,deliverResult會調用到LoaderInfo的onLoadComplete(),這個方法中有這麼一段代碼:

// Notify of the new data so the app can switch out the old data before
// we try to destroy it.
if (mData != data || !mHaveData) {
    mData = data;
    mHaveData = true;
    if (mStarted) {
        callOnLoadFinished(loader, data);
    }
}

data是咱們經過deliverResult傳入的對象,mData是LoaderInfo中一直持有的原對象。只有在這兩個對象不同時纔會執行onLoadFinish方法。因此若是咱們已經調用過deliverResult傳入過數據,以後在loader中僅是改變data的值再傳入,mData和data的值永遠是同樣的,這樣就會形成第一次forceLoad(或deliveResult)時會觸發onLoadFinish,再調用一次就不會觸發。因此咱們須要注意,傳遞給deliverResult的參數好比是新建的對象。能夠是局部新new的變量,也能夠每次都使用clone傳入。這兩種方法經測試均可行且不會引發內存泄露。

4. 總結

Loader中有不少方法能夠複寫,AsyncTaskLoader中提供了不少Loader的抽象方法實現,也提供了一些新的方法,好比loadInBackground,也均可以複寫,靈活性較高。使用的時候咱們要閱讀其源碼搞清楚調用流程,再根據本身的項目須要,複寫相關的方法。

完整代碼能夠參考:https://github.com/Gnepux/Android-Instrument/tree/master/app/src/main/java/com/gnepux/instrument/activity/loader

參考資料

Loader簡單分析 AsyncTaskLoader簡單使用

Android異步任務處理之AsyncTaskLoader的使用

相關文章
相關標籤/搜索