原文地址:http://www.grokkingandroid.com/using-loaders-in-android/
安卓3.0引入Loaders机制让开发者更方便的获取database和Contentprovider中的数据,Loaders机制异步加载数据并且加载完成后会通知监听者们。
(下面一段说你不能在UI线程怎么怎么样。。会ANR。。巴拉巴拉。。)
The classes and interfaces of the Loader API | |
Class | Usage |
LoaderManager | Manages your Loaders for you. Responsible for dealing with the Activity or Fragment lifecycle |
LoaderManager.LoaderCallbacks | A callback interface you must implement |
Loader | The base class for all Loaders |
AsyncTaskLoader | An implementation that uses an AsyncTask to do its work |
CursorLoader | A subclass of AsyncTaskLoader for accessing ContentProvider data |
LoaderManager
这 个类使你的Loaders生命周期与activity或者fragment同步,如果Android destroy了你的fragments或者activities,LoaderManager会通知已被管理的loaders释放资源。 LoaderManager还负责保持你的数据当配置变化时,例如屏幕方向,并且当数据变化时调用相关的回调方法。总而言之:LoaderManager 比已过时的startManagingCursor和managedQuery方法强大很多。
你会经常用到下面两个方法 initLoader()和restartLoader()
initLoader()
The initLoader() method adds a Loader to the LoaderManager:
getLoaderManager().initLoader(LIST_ID, null, this);
It takes three arguments:
a unique ID for this loader,
an optional Bundle with arguments for your Loader and
a LoaderCallbacks interface
为了让你的代码可读性更好,使用final static来为你的loader声明ID,Bundle可以传一些额外的参数为你的Loader,但是!当你使用CursorLoader时,这个参数没有用。
initloader() 方法会创建一个新的Loader对象当ID没有被其他Loader使用时。注意 Android为你处理配置的变化,因为屏幕方向上一个简单的变化会引发再一次调用initLoader(),这种情况下这个方法会返回已经存在的实例并 且你的query不会再次被执行。
restartLoader()
因为Android不会再次执行query操作,你需要重新实例化你的Loader当数据(被用于构造query的数据)变化时。典型的应用是搜索查询。
LoaderManager.LoaderCallbacks
LoaderCallbacks接口定义了你必须实现的方法用以创建一个Loader。为了处理结果数据和资源清理。
public class YourFragment extends Fragment
implements LoaderCallbacks<Cursor> {
//…}
The methods you have to implement are:
onCreateLoader(),
onLoadFinished() and
onLoadReset()
onCreateLoader()
LoaderManager调用这个方法当你第一次调用initLoader()时。
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
CursorLoader loader = new CursorLoader(
this.getActivity(),
SOME_CONTENT_URI,
projection,
selection,
selectionArgs,
sortOrder);
return loader;}
这个参数id和args就是initLoader时传入的参数。如果需要多个Loader你需要根据id创建更多的ifelse分支
onLoadFinished()
这个方法是最有趣的,你可以在此处根据查询的结果更新UI。
对于ListAdapters 你只需要swap这个cursor
This is how it looks in the sample project:
public void onLoadFinished(Loader<Cursor> loader,Cursor cursor) {
if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
int idIndex =
cursor.getColumnIndex(LentItems._ID);
int nameIndex =
cursor.getColumnIndex(LentItems.NAME);
int borrowerIndex =
cursor.getColumnIndex(LentItems.BORROWER);
this.itemId = cursor.getLong(idIndex);
String name = cursor.getString(nameIndex);
String borrower = cursor.getString(borrowerIndex);
((EditText)findViewById(R.id.name)).
setText(name);
((EditText)findViewById(R.id.person)).
setText(borrower);
}}
onLoadReset()
This method allows you to release any resources you hold, so that the Loader can free them. You can set any references to the cursor object you hold to null.
But do not close the cursor – the Loader does this for you.