AsyncTaskLoader用法

关于Loader的基础介绍可以参考:https://my.oschina.net/u/3026396/blog/824550

本章主要通过一个简单的例子阐述AsyncTaskLoader的用法和注意事项。

1. AsyncTaskLoader简介

AsyncTaskLoader是Loader的子类,其内部通过AsyncTask实现数据异步加载。

2. AsyncTaskLoader用法

步骤一:创建一个Loader类继承AsyncTaskLoader,并实现其相关抽象方法。比如:

  • onStartLoading:注册一些监听器到loader上,并且执行一次forceLoad(); 否则loader不会开始工作。如果创建loader时不需要它立刻工作可以不用调用forceLoader。
  • loadInBackground:不用说,在这里就是加载数据并且返回,其实这个数据就返回到了LoaderManager的onLoadFinished方法第二个参数 
  • onStopLoading:停止加载数据,但不要停止监听也不要释放数据,就可以随时重启loader 
  • onReset:先确保已经停止加载数据了,然后释放掉监听器并设为null 
  • onCanceled: 在这里可以释放资源,如果是list就不需要做什么了,但是象cursor或者打开了什么文件就应该关闭一下;
  • deliverResult:分发数据。

步骤二:获取LoaderMananger:

LoaderMananger mananger = getSupportLoaderManager();

步骤三:创建LoaderMananger.LoaderCallbacks回调

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);

步骤五:启动Loader

mNewsLoader.forceLoad();

步骤六:Loader的其他操作

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

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

步骤七:我们可以在数据源中添加监听接口,在Loader中实现该接口,在该接口中触发某些动作,比如forceLoad或deliveResult。

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的使用

转载于:https://my.oschina.net/u/3026396/blog/830441

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值