Android异步处理技术——Loader



Loader使得在Activity或Fragment中异步加载数据变得方便,它在数据源发生变化时,能够及时发出消息通知。
一 Loader
1.1 常用类
AsyncTaskLoader:一个提供异步任务的加载器
CursorLoader:一个用来查询数据库相关的加载器,是AsyncTaskLoader的子类。 
1.2 回调方法
重要的回调
onStartLoading()
onStopLoading()
onReset()
onForceLoad()           // from Loader            
ORloadInBackground()   // from AsyncTaskLoader
可选的回调
deliverResult() [override]
1.3 建立一个Loader类
Loader只能是static的,不然的话就会保持一个对outer class的引用。
 


 
 
输出日志:
initLoader时:


 
退出activity时


  
分析:
initLoader时首先调用callback中的onCreateLoader方法,返回一个loader,然后loaderManager开始管理这个loader,直接执行loader的onStartLoading方法,我们可以在这里做点准备工作,准备工作做完了后就通过forceLoad()来执行loadInBackground()方法,在这里进行加载各种数据,这个方法执行完毕后在callback中就会自动调用onLoadFinished()方法,告诉activity已经加载结束了,并且在public void onLoadFinished(Loader loader, Object data) 中,我们可以得到结果的data对象。
分析:回调方法所在的线程
这个完全可以类比到AsyncTask,之前也有预料到,loadInBackground()是在主线程之外的线程运行的,其余的回调方法都是在主线程运行的。所以可以这么理解onStartLoading()做一些初始化的工作,真正做处理的代码要放在loadInBackground()中,loadInBackground()中的代码执行完毕后会自动传输数据,我们在callback回调中接收就好了。至于怎么结束,我们可以不怎么管它,因为在当前activity退出时,它会自动调用onStop(),onRest(),这里面可以做收尾工作。
 1.4 CursorLoader
CursorLoader继承自AsyncLoader,所以就不在多说了,它主要处理数据查询方面的工作。
 
二、LoaderManager.LoaderCallbacks回调的方法
2.1 onCreateLoader
当试图访问一个装载器时(例如,通过initLoader()),它会检查那个装载器是否被已存在的id所指定。如果它没有,它将触发LoaderManager.LoaderCallbacks 的onCreateLoader()方法。
在下面例子中,onCreateLoader()回调方法创建了一个CursorLoader。使用它的构造方法来创建一个CursorLoader,它需要对ContentProvider执行一个查询所需要的全套的信息。它可能需要:
Uri:要检索内容的URI。
Projection:要返回的某一列元素的列表。传递空将返回所有列的元素的集合,这是不高效的。
Selection:声明要返回哪些行的过滤器,按照SQL的where语句格式化(包含where本身)。传递null将会返回给定URI的所有行。
selectionArgs:在Selection中可以包含多个?,它们将会被从selectionArgs中得到的值所替代,使它们显示在selection中。这些值将会被绑定为字符串。
sortOrder:如何对行进行排序,被格式化成SQL ORDER BY 子句(包含ORDER BY 本身)。传递空值将会使用默认排序,那也许是无序的。
 
这个loader是查询数据库的,交给这个loader进行处理的前先把数据的URI,查询的语句(select),排序方式(order by)等等作为构造函数的参数传递到loader中,这个loader用这些东西去查就好了。
2.2 onLoadFinished
当先前创建的装载器已经完成它的装载工作时此方法将会被调用。这个方法要保证在为这个装载器提供的最终数据释放之前被调用。在此刻你应该清除掉所有使用的旧数据(由于它将很快被释放),但是不要清除你自己传递(发布)的数据,因为它的装载机拥有它并将管理它。
一旦装载机知道应用程序不再使用那些数据就会释放它们。例如,如果数据是从一个CursorLoader返回的cursor,你自己就应该调用它的close()方法。如果游标被放置在一个CursorAdapter中,你应该使用swapCursor()方法以便旧的Cursor也被关掉。例如:
 
2.3 onLoaderReset
当先前被创建的装载机被重置的时候这个方法就被调用,从而使它的数据无效。这个回调可以让你找到数据什么时候将要被释放,这样你就可以释放掉对它的引用。如果游标被放置在一个CursorAdapter中,你应该实现调用swapCursor同时传递一个空值。
 
三 给Loader添加进度
3.1 添加进度
Loader不像AsyncTask那样可以有一个进度的回调方法,所以这里要通过LocalBroadcastManager来进行处理。通过广播的形式来传递进度,下面仅仅是一个举例。

@Override
protected void onStart() {
        //Receive loading status broadcasts in order to update the progress bar
        LocalBroadcastManager.getInstance(this).registerReceiver(loadingStatusReceiver, new IntentFilter(MyLoader.LOADING_ACTION));
        super.onStart();
    }
    @Override
    protected void onStop() {
        super.onStop();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(loadingStatusReceiver);
    }

    @Override
    public Result loadInBackground() {
        // Show progress bar
        Intent intent = new Intent(LOADING_ACTION).putExtra(LOADING_EXTRA,true);
        LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
        try {
            return doStuff();
        } finally {
            // Hide progress bar
            intent = new Intent(LOADING_ACTION).putExtra(LOADING_EXTRA, false);
            LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
        }
    }


开始的时候建立广播对象,结束的时候注销广播,在运行的时候可以在某个时期发送广播。
 
3.2 添加错误处理
当遇到error的时候通常只能简单的返回null。
解决方法:
① 封装一个结果和exception。比如Pair<T,Exception>。你的Loader的cache需要更智能一些,他可以检查result是否为null或者是否有error。
② 在Loader中加入一个exception的变量。如果在出错的时候给这个变量赋值,在finish时传递出去这个值,然后我们就可以在callback中进行检查处理了。
 
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值