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

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;
            }

这样就达到了重新连接并且不需要再次查询的目的。


你可能感兴趣的:(Android Loader(三) 结合CursorLoader分析Loader相关源码)