LoadTask继承AsyncTask类,重写了
doInBackground/ onPostExecute/ onCancelled三个方法,但是并没有重写onProgressUpdate,所以并不能更新进度信息。
doInBackground方法运行于线程池的线程中。
流程图如下,
CursorLoader的loadInBackground方法如下,
public Cursor loadInBackground() { synchronized (this) { if (isLoadInBackgroundCanceled()) { throw new OperationCanceledException(); } mCancellationSignal = new CancellationSignal(); } try { Cursor cursor = getContext().getContentResolver().query(mUri, mProjection, mSelection, mSelectionArgs, mSortOrder, mCancellationSignal); if (cursor != null) { try { // Ensure the cursor window is filled. cursor.getCount(); cursor.registerContentObserver(mObserver); } catch (RuntimeException ex) { cursor.close(); throw ex; } } return cursor; } finally { synchronized (this) { mCancellationSignal = null; } } }开始异步查询数据库。
ContactEntryListFragment创建CursorLoader时虽然重写了onLoadInBackground方法,但是和没写差不多。只是打了个log。
public CursorLoader createCursorLoader(Context context) { return new CursorLoader(context, null, null, null, null, null) { @Override protected Cursor onLoadInBackground() { try { return super.onLoadInBackground(); } catch (RuntimeException e) { // We don't even know what the projection should be, so no point trying to // return an empty MatrixCursor with the correct projection here. Log.w(TAG, "RuntimeException while trying to query ContactsProvider."); return null; } } }; }onCancelled运行于主线程(UI)线程中。
流程图如下,
CursorLoader的onCanceled方法如下,
@Override public void onCanceled(Cursor cursor) { if (cursor != null && !cursor.isClosed()) { cursor.close(); // 关闭查询数据库的cursor } }onPostExecute运行于主线程(UI)线程中。
流程图如下,
Loader的deliverResult方法如下,
public void deliverResult(D data) { if (mListener != null) { mListener.onLoadComplete(this, data); } }onLoadComplete是一个回调方法,调用谁的呢?
在3.1 小节的最后LoaderInfo的start方法会调用回调方法onCreateLoader 创建的mLoader 的registerListener和registerOnLoadCanceledListener方法,
mLoader.registerListener(mId, this); mLoader.registerOnLoadCanceledListener(this);LoaderInfo的定义如下,
final class LoaderInfo implements Loader.OnLoadCompleteListener<Object>, Loader.OnLoadCanceledListener<Object> {继承了Loader的2个接口, OnLoadCompleteListener和OnLoadCanceledListener
接口的定义如下,
public interface OnLoadCompleteListener<D> { public void onLoadComplete(Loader<D> loader, D data); } public interface OnLoadCanceledListener<D> { public void onLoadCanceled(Loader<D> loader); }registerListener方法如下,
public void registerListener(int id, OnLoadCompleteListener<D> listener) { if (mListener != null) { throw new IllegalStateException("There is already a listener registered"); } mListener = listener; mId = id; }mListener变量是一个OnLoadCompleteListener子类对象,
OnLoadCompleteListener<D> mListener;onLoadComplete方法,调用流程图如下,
内部类LoaderInfo 的callOnLoadFinished方法如下,
void callOnLoadFinished(Loader<Object> loader, Object data) { if (mCallbacks != null) { String lastBecause = null; if (mHost != null) { lastBecause = mHost.mFragmentManager.mNoTransactionsBecause; mHost.mFragmentManager.mNoTransactionsBecause = "onLoadFinished"; } try { if (DEBUG) Log.v(TAG, " onLoadFinished in " + loader + ": " + loader.dataToString(data)); mCallbacks.onLoadFinished(loader, data); } finally { if (mHost != null) { mHost.mFragmentManager.mNoTransactionsBecause = lastBecause; } } mDeliveredData = true; } }回调ContactEntryListFragment的onLoadFinished方法。
如果数据库的值发生了变化,UI界面如何知晓并随之更新呢?例如,新增或者删除部分联系人,UI界面立刻就会更新,是如何实现的呢?
Loader里有个内部类ForceLoadContentObserver,定义如下,
public final class ForceLoadContentObserver extends ContentObserver { public ForceLoadContentObserver() { super(new Handler()); } @Override public boolean deliverSelfNotifications() { return true; } @Override public void onChange(boolean selfChange) { onContentChanged(); } }看到没有,典型的观察者模式。
那么,在什么时候注册的呢?
在CursorLoader的构造方法中,会实例化ForceLoadContentObserver对象,
public CursorLoader(Context context) { super(context); mObserver = new ForceLoadContentObserver(); }在CursorLoader的loadInBackground方法中调用Cursor的registerContentObserver方法完成注册,
try { // Ensure the cursor window is filled. cursor.getCount(); cursor.registerContentObserver(mObserver); } catch (RuntimeException ex) { cursor.close(); throw ex; }注册完之后,数据库一旦有变化,就会回调内部类ForceLoadContentObserver的onChange方法,调用流程图如下,
AsyncTaskLoader 的onForceLoad方法如下,
@Override protected void onForceLoad() { super.onForceLoad(); cancelLoad(); mTask = new LoadTask(); if (DEBUG) Log.v(TAG, "Preparing load: mTask=" + mTask); executePendingTask(); // 重新利用线程池查询 }当监听到数据库的内容发生变化,回调方法就会强制查询刷新,这样达到了监听的目的。
1, LoaderManager
LoaderManager并不知道数据如何加载以及何时加载,只是控制它的Loaders开始,停止,重置等行为。
2,异步操作以及线程的管理都是通过AsyncTask来管理的
相比于AsyncTask, LoaderManager有什么优点呢?
LoaderManager最大的好处是可以对数据库进行监听,当数据库改变,客户端可以更新数据。