您的位置:首页 > 移动开发 > Android开发

Android Loader(三) 结合CursorLoader分析Loader相关源码

2014-11-30 18:09 483 查看
Android Loader(二) CursorLoader

Android Loader(四) 自定义Loader从网络中获取文本数据

首先从加载数据的过程开始分析。

初始化Loader的方法是:getLoaderManager().initLoader(0, null, this);当这个方法调用之后,Loader就在后台进行初始化,以及数据加载的工作了。

先看一下LoaderManager代码,LoaderManager是一个抽象类,LoaderCallbacks是其内部类,LoaderCallbacks有onCreateLoader,onLoadFinished,onLoaderReset三个方法。

LoaderManager的关键抽象方法有:initLoader,restartLoader,destroyLoader,getLoader,他们都是通过LoaderManager的子类LoaderManagerImpl实现的。

class LoaderManagerImpl extends LoaderManager

LoaderManagerImpl的内部类LoaderInfo:

final class LoaderInfo implements Loader.OnLoadCompleteListener<Object>,

Loader.OnLoadCanceledListener<Object> {

LoaderManagerImpl有2个全局变量SparseArray<LoaderInfo> mLoaders和SparseArray<LoaderInfo> mInactiveLoaders,mLoaders中存放着当前活动的Loader,mInactiveLoaders存放着以前运行的Loader。

下面从初始化Loader开始分析:

先看getLoaderManager().方法, 实际调用的是Activity的LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) ,返回一个LoaderManagerImpl,

LoaderManagerImpl的initLoader中的关键代码:

LoaderInfo info = mLoaders.get(id);

if (info == null) {

info = createAndInstallLoader(id, args,  (LoaderManager.LoaderCallbacks<Object>)callback);

}
createAndInstallLoader:

private LoaderInfo createAndInstallLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<Object> callback) {
try {
mCreatingLoader = true;
LoaderInfo info = createLoader(id, args, callback);
installLoader(info);
return info;
} finally {
mCreatingLoader = false;
}
}
createLoader:

private LoaderInfo createLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<Object> callback) {
LoaderInfo info = new LoaderInfo(id, args,  (LoaderManager.LoaderCallbacks<Object>)callback);
Loader<Object> loader = callback.onCreateLoader(id, args);
info.mLoader = (Loader<Object>)loader;
return info;
}
可以看到, LoaderInfo通过 createLoader实例化,并且在createLoader中,调用LoaderCallbacks的onCreateLoader创建Loader,onCreateLoader在实现了LoaderCallbacks的Fragment或Activity中实现,这样就完成了Loader的创建。再看 installLoader方法:

void installLoader(LoaderInfo info) {
mLoaders.put(info.mId, info);
if (mStarted) {
info.start();
}
}
mStarted的值为true,赋值过程如下:

LoaderManagerImpl构造方法:

LoaderManagerImpl(String who, Activity activity, boolean started) {
mWho = who;
mActivity = activity;
mStarted = started;
}
这是在Activity的 getLoaderManager中调用的:

lm = new LoaderManagerImpl(who, this, started);
started的值在Fragment的getLoaderManager调用中赋值

mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, true);
这个 mLoadersStarted是全局变量,在Fragment的onStart方法中赋值

Fragment.onStart():

protected void onStart() {
......

if (!mLoadersStarted) {
mLoadersStarted = true;
if (mLoaderManager != null) {
mLoaderManager.doStart();
} else if (!mCheckedForLoaderManager) {
mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false);
}
mCheckedForLoaderManager = true;
}
getApplication().dispatchActivityStarted(this);
}
再回到installLoader方法,info.start()被调用,start方法:

......
mStarted = true;
......
if (!mListenerRegistered) {
mLoader.registerListener(mId, this);
mLoader.registerOnLoadCanceledListener(this);
mListenerRegistered = true;
}
mLoader.startLoading();


Loader.startLoading():

public final void startLoading() {
mStarted = true;
mReset = false;
mAbandoned = false;
onStartLoading();
}


查看Loader类的说明:

Subclasses generally must implement at least onStartLoading(),onStopLoading(), onForceLoad(), onReset()

onStartLoading方法是需要Loader的子类重写的,以CursorLoader为例:

@Override
protected void onStartLoading() {
if (mCursor != null) {
deliverResult(mCursor);
}
if (takeContentChanged() || mCursor == null) {
forceLoad();
}
}
deliverResult():

public void deliverResult(D data) {
if (mListener != null) {
mListener.onLoadComplete(this, data);
}
}
从以上代码可以看出, 如果mCursor不为空,则说明数据查询已经结束, 直接调用onLoadComplete, mListener对象是 Loader内部接口 OnLoadCompleteListener的实例:

OnLoadCompleteListener<D> mListener;
public interface OnLoadCompleteListener<D> {
public void onLoadComplete(Loader<D> loader, D data);
}


onLoadComplete中调用了 callOnLoadFinished方法,callOnLoadFinished中调用了 onLoadFinished:

mCallbacks.onLoadFinished(loader, data);


onLoadFinished也是需要重写的方法,一般在使用CursorLoader的类中, LoaderCallbacks的onLoadFinished方法都这样实现:

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.swapCursor(data);
}
再来看onStartLoading中的另外一个判断语句:

if (takeContentChanged() || mCursor == null) {
forceLoad();
}
forceLoad:

public void forceLoad() {
onForceLoad();
}


onForceLoad在CursorLoader的父类 AsyncTaskLoader中已经重写,一般自定义的Loader不直接继承Loader,而是继承 AsyncTaskLoader,CursorLoader也是如此。

@Override
protected void onForceLoad() {
super.onForceLoad();
cancelLoad();
mTask = new LoadTask();
if (DEBUG) Slog.v(TAG, "Preparing load: mTask=" + mTask);
executePendingTask();
}
Loader.cancelLoad:

public boolean cancelLoad() {
return onCancelLoad();
}
AsyncTaskLoader.onCancelLoad:

@Override
protected boolean onCancelLoad() {
if (DEBUG) Slog.v(TAG, "onCancelLoad: mTask=" + mTask);
if (mTask != null) {
if (mCancellingTask != null) {
// There was a pending task already waiting for a previous
// one being canceled; just drop it.
if (DEBUG) Slog.v(TAG,
"cancelLoad: still waiting for cancelled task; dropping next");
if (mTask.waiting) {
mTask.waiting = false;
mHandler.removeCallbacks(mTask);
}
mTask = null;
return false;
} else if (mTask.waiting) {
// There is a task, but it is waiting for the time it should
// execute.  We can just toss it.
if (DEBUG) Slog.v(TAG, "cancelLoad: task is waiting, dropping it");
mTask.waiting = false;
mHandler.removeCallbacks(mTask);
mTask = null;
return false;
} else {
boolean cancelled = mTask.cancel(false);
if (DEBUG) Slog.v(TAG, "cancelLoad: cancelled=" + cancelled);
if (cancelled) {
mCancellingTask = mTask;
cancelLoadInBackground();
}
mTask = null;
return cancelled;
}
}
return false;
}
这个方法的作用是取消之前没有或者正在执行的 mTask, mTask是一个AsyncTask。

之前提到,Loader的子类必须实现的方法之一是onStopLoading,CursorLoader中的onStopLoading实际上就间接调用了onCancelLoad:

@Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
继续看onForceLoad的代码:

mTask = new LoadTask();
executePendingTask();

LoadTask就是个AsyncTask, LoadTask的doInBackground中:

D data = AsyncTaskLoader.this.onLoadInBackground();
return data;
protected D onLoadInBackground() {
return loadInBackground();
}
Loader异步的特性就是通过这个AsyncTask实现的,executePendingTask方法启动这个task,Loader的子类重写LoadInBackground完成数据的异步加载。这个方法在CursorLoader的实现如下:

@Override
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;
}
}
}
在这段代码中,对指定URI的查询结果放入Cursor对象,然后在 LoadTask的onPostExecute中处理:

@Override
protected void onPostExecute(D data) {
if (DEBUG) Slog.v(TAG, this + " onPostExecute");
try {
AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);
} finally {
mDone.countDown();
}
}
dispatchOnLoadComplete中,调用了deliverResult,这样,在onLoadFinished中就能获取Cursor数据。

以上是一个Loader从创建到初始化到加载并传递数据的过程。

Loader的onReset也是需要子类重写的方法,AsyncTaskLoader没有实现这个方法,CursorLoader的实现如下:

@Override
protected void onReset() {
super.onReset();

// Ensure the loader is stopped
onStopLoading();

if (mCursor != null && !mCursor.isClosed()) {
mCursor.close();
}
mCursor = null;
}
onReset方法做了2件事,调用onStopLoading和关闭cursor, onRest方法在Loader的reset中被调用,而reset在LoaderManagerImpl的destroy() 调用, destroy()这个方法是在Loader需要销毁时调用的,所以onReset中应该实现停止加载数据和释放资源的逻辑。

Loader可以探测到数据源的变化并且自动加载,这个特性,用CursorLoader的代码来解读:

先看CursorLoader的构造方法:

public CursorLoader(Context context) {
super(context);
mObserver = new ForceLoadContentObserver();
}
ForceLoadContentObserver是Loader的内部类,它是ContentObserver的子类,在Cursor的loadInBackground() 中,向这个Observer进行了注册:

cursor.registerContentObserver(mObserver);
这里使用了观察者模式, ForceLoadContentObserver是Obeserver,Cursor是Subject,当Cursor内容改变时,ForceLoadContentObserver的onChange方法会被调用,进而调用onContentChanged():

@Override
public void onChange(boolean selfChange) {
onContentChanged();
}


onContentChanged:

public void onContentChanged() {
if (mStarted) {
forceLoad();
} else {
// This loader has been stopped, so we don't want to load
// new data right now...  but keep track of it changing to
// refresh later if we start again.
mContentChanged = true;
}
}
内部调用了 forceLoad对数据进行重新加载,所以CursorLoader在数据源发生变化时可以重新加载数据。

最后来看一下为什么CursorLoader可以在configuration change时重新连接Cursor:
在 configuration change时,Activity会被销毁并重建,不论Fragment还是Activity都会调用onStart这个回调 ,onStart中的 mLoaderManager.doStart(),调用了LoaderManager的doStart();

void doStart() {
if (DEBUG) Log.v(TAG, "Starting in " + this);
if (mStarted) {
RuntimeException e = new RuntimeException("here");
e.fillInStackTrace();
Log.w(TAG, "Called doStart when already started: " + this, e);
return;
}

mStarted = true;

// Call out to sub classes so they can start their loaders
// Let the existing loaders know that we want to be notified when a load is complete
for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).start();
}
}


mLoader中的Loader是在 installLoader方法中添加的:mLoaders.put(info.mId, info);
for循环中,从 mLoaders中获取正在运行的Loader,重新调用它们的 start方法,在start中有以下判断:

if (mRetaining && mRetainingStarted) {
// Our owner is started, but we were being retained from a
// previous instance in the started state...  so there is really
// nothing to do here, since the loaders are still started.
mStarted = true;
return;
}

if (mStarted) {
// If loader already started, don't restart.
return;
}


这样就达到了重新连接并且不需要再次查询的目的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: