LoaderManager源码分析之二
来源:互联网 发布:手机扣字软件 编辑:程序博客网 时间:2024/06/10 07:20
4, LoadTask三部曲
LoadTask继承AsyncTask类,重写了
doInBackground/ onPostExecute/ onCancelled三个方法,但是并没有重写onProgressUpdate,所以并不能更新进度信息。
4.1, doInBackground
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; } } }; }
4.2, onCancelled
onCancelled运行于主线程(UI)线程中。
流程图如下,
CursorLoader的onCanceled方法如下,
@Override public void onCanceled(Cursor cursor) { if (cursor != null && !cursor.isClosed()) { cursor.close(); // 关闭查询数据库的cursor } }
4.3, onPostExecute
onPostExecute运行于主线程(UI)线程中。
流程图如下,
Loader的deliverResult方法如下,
public void deliverResult(D data) { if (mListener != null) { mListener.onLoadComplete(this, data); } }
onLoadComplete是一个回调方法,调用谁的呢?
5, 注册和回调
在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方法。
6, 观察者模式监听数据库的变化
如果数据库的值发生了变化,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(); // 重新利用线程池查询 }
当监听到数据库的内容发生变化,回调方法就会强制查询刷新,这样达到了监听的目的。
7, 小结
1, LoaderManager
LoaderManager并不知道数据如何加载以及何时加载,只是控制它的Loaders开始,停止,重置等行为。
2,异步操作以及线程的管理都是通过AsyncTask来管理的
相比于AsyncTask, LoaderManager有什么优点呢?
LoaderManager最大的好处是可以对数据库进行监听,当数据库改变,客户端可以更新数据。
- LoaderManager源码分析之二
- LoaderManager源码分析之一
- android之LoaderManager原理分析
- Memcached源码分析之二
- AsyncTask源码分析之二
- AndFix 源码分析之二
- ContentProvider 源码分析---之二
- LoaderManager使用详解(二)---了解LoaderManager
- LoaderManager使用详解(二)---了解LoaderManager
- LoaderManager使用详解(二)---了解LoaderManager
- LoaderManager使用详解(二)---了解LoaderManager
- LoaderManager使用详解(二)---了解LoaderManager
- LoaderManager使用详解(二)---了解LoaderManager
- LoaderManager使用详解(二)---了解LoaderManager
- LoaderManager使用详解(二)---了解LoaderManager
- LoaderManager使用详解(二)---了解LoaderManager
- LoaderManager使用详解(二)---了解LoaderManager
- LDD3源码分析之llseek分析(二)
- TensorFlow【机器学习】:如何正确的掌握Google深度学习框架TensorFlow(第二代分布式机器学习系统)?
- 谈一谈几种处理 JavaScript 异步操作的办法
- Android Realm数据库使用指南
- HTTP验证大法(Basic Auth,Session, JWT, Oauth, Openid)
- 为什么要重视数学?机器学习需要哪些数学基础?
- LoaderManager源码分析之二
- jvm系列(七):jvm调优-工具篇
- cdoj1057 秋实大哥与花 线段树 区间加,区间查询和
- 自己写LinkedList GoLinkedList
- 驾校科目三考试项目
- UE4入门 1 如何在空项目中创建Actor并显示在游戏中 C++
- 【Android】自定义控件让TextView的drawableLeft与文本一起居中显示
- Lock和synchronized比较详解
- javaweb分布式_zookeeper