Loaders已经成为获取数据库或者内容提供者中的数据的首选方案。
它可以异步的加载数据并当数据改变时及时提醒监听器。
Google不仅仅是推荐你使用Loader,而且deprecated 掉一些先前处理Cursor的方法。现在你不应该在你的项目中再使用startManagingCursor()和managedQuery()方法了。
使用cursor查询通常是执行在主线程(UI Thread)中,这可能会使应用有些反应迟钝甚至会导致ANR(application not responding)问题,而使用Loaders将不会再阻塞你的主线程。
在这篇博客中我将介绍Loader API中一些主要的类并向您展示如何使用他们。
Loader API中主要的类和接口
下面我将逐一介绍这些类,首先从LoaderManager开始吧!
LoaderManager
这个类使你的Loaders与Activity以及Frgament的生命周期保持一致。如果销毁了Frgament或者Activity,那么LoaderManager将会释放Loaders占用的资源。总之,这个类比先前的startManagingCursor或者managedQuery方法更加厉害。
你并不需要自己实例化这个类,仅需在Activity或者Frgament中调用getLoaderManager()方法即可。
通常情况下你仅需要了解下面两个方法就足够了:
1.initLoader()
2.restartLoader()
initLoader()
这个方法将向LoaderManager中添加一个Loader:
getLoaderManager().initLoader(id,
bundle, callbacks);
;
该方法需要传入三个参数:
一个id号用来唯一标识Loader,一个Bundle对象,以及LoaderCallbacks接口。
你可能需要一个id号以便于将来调用方便,所以请尽量将id号声明为final static的,这样会使你的代码可读性更好。Bundle用来为你的Loader传递一些可选的参数,但是对于CursorLoader并不适用。第三个参数,LoaderCallbacks,我们在下面将会详细介绍。
initLoader方法创建一个新的Loader的前提是对应的id号之前没有被使用过。需要牢记的是系统会为你处理配置改变的情形,所以一些小小的变化都会都会调用initLoader方法,在这种情形下,这个方法会返回已有的实例所以你的查询操作将不会被再次执行。
因为系统不会再次处理查询操作,所以需要一个方法重新加载Loader当数据发生改变时,你可以使用restartLoader方法来重置Loader,它的参数类型和initLoader一样,当然你需要传入一个和初始化Loader时相同的id号。
getLoaderManager().restartLoader(id,
bundle, callbacks);
你必须实现的方法如下:
onCreateLoader()
onLoadFinished()
onLoadReset()
下面我们逐一解释每个方法的作用:
当你第一次调用initLoader时会调用此方法。就像之前提到过的,前提是对应的ID不存在。
另外还需要传递一个int类型和一个bundle类型的参数,这跟initLoader中的参数意义是一样的。
一个典型的创建CursorLoader的示例代码如下:
我们可以看到CursorLoader中的参数就是ContentResolver处理查询操作所需的参数。
如果你需要执行不同的查询操作并因此使用了不同的id创建Loaders,你仅需增加一个if-else分支判断即可。
这个方法最有意思了,你可以在这里根据查询的结果更新你的UI。如果是ListAdapter的话仅需swap一下cursor即可。否则你需要得到view对象相关控件的引用并根据结果对其赋值。
这个方法允许你释放你持有的资源,以便Loader来释放它们。你可以将相关对象置为null但是不要关闭cursor,因为Loader会帮我们完成。
Loader及其实现类并不是很有意思除非你编写自己的Loader。当然你不得不创建一个Loader,但是除了使用构造器创建CursorLoader你几乎不和这些对象打交道。
如果你使用不同的Loader你需要在callbacks方法中获取它们的id,可以通过在Loader中调用getId()方法传递给callbacks。
使用CursorLoader需要注意的地方
通常我们都会把cursorLoader作为ListView或者AutoCompleteTextViews
等控件的数据源。在使用Loader时务必得小心:
首先,Cursor对象在onLoadFinished方法调用之前是不存在的,换句话说,当你创建好了适配器,Cursor对象未必可用,所以当你创建适配器时需要将cursor参数置空:
当cursor对象可用时你必须加上它,可以使用在适配器中调用swapCursor方法:
在onLoadReset方法中清理资源时重新调用swapCursor方法并传入null
为了兼容老版本,google提供了扩展库,最主要的包括Frgament和Loader。
你应该尽量使用扩展库中的API以使你的应用兼容性更好。但是在你导包的时候务必睁大眼睛报名开头是android.support.v4
:
通过继承FrgamentActivity,获取LoaderManager实例的方法变为getSupportLoaderManager()。
如果你需要你的后台任务完成的话请不要使用Loader。因为Loader会随着Frgament或者Activity的销毁而销毁。如果需要执行一些后台任务,请使用service代替。
原文地址:http://www.grokkingandroid.com/using-loaders-in-android/