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最大的好处是可以对数据库进行监听,当数据库改变,客户端可以更新数据。

0 0
原创粉丝点击