LoaderManager和AsyncTaskLoader详解

LoaderManager是什么?

简单的理解是,LoaderManager用来负责管理与Activity或者Fragment联系起来的一个或多个Loaders对象。每个Activity或者Fragment都有唯一的一个LoaderManager实例,用来启动、停止、保持、重启、关闭它的Loaders。这些事件有时直接在客户端通过调用initLoader()/restartLoader()/destroyLoader()函数来实现。通常这些事件通过主要的Activity/Fragment声明周期事件来触发,而不是手动(当然也可以手动调用)。

LoaderManager并不知道数据如何装载以及何时需要装载。相反地,LoaderManager只需要控制它的Loaders们开始、停止、重置他们的Load行为,在配置变换(比如横竖屏切换)时保持loaders们的状态,并提供一个简单的接口来获取load结果到客户端中。

LoaderManager为你初始化、管理、销毁Loaders,减少了代码复杂度和与Activity或者Fragment生命周期相关的bug。更多地,与LoaderManager交互需要实现三个简单的回调方法。当然,首先我们要继承LoaderCallbacks。继承以后就会自动添加三个回调方法:

  1. onCreateLoader是一个工厂方法,用来返回一个新的Loader。LoaderManager将会在它第一次创建Loader的时候调用该方法。
  2. onLoadFinished方法将在Loader创建完毕的时候自动调用。典型用法是,当载入数据完毕,客户端(译者注:调用它的Activity之类的)需要更新应用UI。客户端假设每次有新数据的时候,新数据都会返回到这个方法中。记住,检测数据源是Loader的工作,Loader也会执行实际的同步载入操作。一旦Loader载入数据完成,LoaderManager将会接受到这些载入数据,并且将将结果传给回调对象的onLoadFinished方法,这样客户端(比如Activity或者Fragment)就能使用该数据了。
  3. 最后,当Loader们的数据被重置的时候将会调用onLoadReset。该方法让你可以从就的数据中移除不再有用的数据。
public class Test extends Activity implements LoaderCallbacks<List<String>>{

    //是一个工厂方法,用来返回一个新的Loader
    //LoaderManager将会在它第一次创建Loader的时候调用该方法。
    //只会调用一次
    @Override
    public Loader<List> onCreateLoader(int id, Bundle args) {
        return null;
    }

    //在Loader创建完毕的时候自动调用
    //每次数据源都有更新的时候,就会回调这个方法,然后update 我们的ui了。
    @Override
    public void onLoadFinished(Loader<List> loader, List data) {

    }

    //移除不再有用的数据
    @Override
    public void onLoaderReset(Loader<List> loader) {
    }
}

Loaders特性

包括:1.在一个单独线程载入数据;2.监测底层数据源,当探测到有改变时就更新或者重新查询。

这些特性最终决定了一个Loader的行为:

  1. 执行异步载入的任务。为了确保在一个独立线程中执行载入操作,Loader的子类必须继承AsyncTaskLoader而不是Loader类。AsyncTaskLoader是一个抽象Loader,它提供了一个AsyncTask来做它的执行操作。当定义子类时,通过实现抽象方法loadInBackground方法来实现异步task。该方法将在一个工作线程中执行数据加载操作。
public class TestLoader extends AsyncTaskLoader<List<String>> {

    public TestLoader(Context context) {
        super(context);
    }

    @Override
    public List loadInBackground() {
        return null;
    }

    protected void onStartLoading() {
        if(takeContentChanged()){//数据有改动
            forceLoad();
        }
    };
}
  1. 在一个注册监听器中接收载入完成返回的结果。对于每个Loader来说,LoaderManager注册一个OnLoadCompleteListener,该对象将通过调用onLoadFinished(Loader loader, D result)方法使Loader将结果传送给客户端。Loader通过调用Loader#deliverResult(D result),将结果传递给已注册的监听器们。
    源码:
    public interface OnLoadCompleteListener {
        /**
         * Called on the thread that created the Loader when the load is complete.
         *
         * @param loader the loader that completed the load
         * @param data the result of the load
         */
        public void onLoadComplete(Loader loader, D data);
    }
        @Override
        public void onLoadComplete(Loader<Object> loader, Object data) {
            ......
            // 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);
                }
            }
            ......
        }

        void callOnLoadFinished(Loader<Object> loader, Object data) {
            if (mCallbacks != null) {
                String lastBecause = null;
                if (mActivity != null) {
                    lastBecause = mActivity.mFragments.mNoTransactionsBecause;
                    mActivity.mFragments.mNoTransactionsBecause = "onLoadFinished";
                }
                try {
                    if (DEBUG) Log.v(TAG, "  onLoadFinished in " + loader + ": "
                            + loader.dataToString(data));
                    mCallbacks.onLoadFinished(loader, data);
                    //注意这里的onLoadFinished
                } finally {
                    if (mActivity != null) {
                        mActivity.mFragments.mNoTransactionsBecause = lastBecause;
                    }
                }
                mDeliveredData = true;
            }
        }

从源代码可以看出,继承了接口然后实现onLoadComplete。在这个函数中调用onLoadFinished

  1. 有一个观察者接受数据源改变的通知。Loader必须实现这些Observer其中之一(比如ContentObserver,BroadcastReceiver等),来检测底层数据源的改变。当检测到数据改变,观察者必须调用Loader#onContentChanged()。在该方法中执行两种不同操作:a. 如果Loader已经处于启动状态,就会执行一个新的载入操作; b. 设置一个flag标识数据源有改变,这样当Loader再次启动时,就知道应该重新载入数据了。

弄明白上面的就可以看下面两篇文章,讲的更深入
Android开发之ContentProvider结合LoaderManager加载数据(图文源代码分享)
Android 异步加载神器 Loader 全解析

你可能感兴趣的:(Android)