1, 基本概念
LoaderManager从名字来看,就是异步任务的意思。
LoaderManager是一个抽象类定义如下,
public abstract class LoaderManager {
还包含一个接口,有三个方法,
public interface LoaderCallbacks<D> {
public Loader<D> onCreateLoader(int id, Bundle args);
public void onLoadFinished(Loader<D> loader, D data);
public void onLoaderReset(Loader<D> loader);
}
实际上, 内部类LoaderManagerImpl是LoaderManager的代理类,负责所有方法的执行。
LoaderManager定义如下,
class LoaderManagerImpl extends LoaderManager {
2, LoaderManager使用
源码中Contacts加载联系人就利用了LoaderManager机制,实现也很简单,继承LoaderCallbacks接口并且实现三个方法就可以了。
ContactEntryListFragment中的实现如下,
导入包
import android.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
继承LoaderCallbacks接口
implements LoaderCallbacks<Cursor>
实现方法,
onCreateLoader方法
public Loader<Cursor> onCreateLoader(int id, Bundle args) {onLoadFinished方法如下,使用完成之后,要调用destroyLoader方法。
if (id == DIRECTORY_LOADER_ID) {
•••
} else {
CursorLoader loader = createCursorLoader(mContext);
long directoryId = args != null && args.containsKey(DIRECTORY_ID_ARG_KEY)
? args.getLong(DIRECTORY_ID_ARG_KEY)
: Directory.DEFAULT;
mAdapter.configureLoader(loader, directoryId);
return loader;
}
}
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;
}
}
};
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
•••
mDirectoryListStatus = STATUS_NOT_LOADED;
getLoaderManager().destroyLoader(DIRECTORY_LOADER_ID);
}
onLoaderReset是一个空的方法,
public void onLoaderReset(Loader<Cursor> loader) {
}
还需要借助于CursorLoader来实现异步查询。
Activity/Fragment 中的getLoaderManager 最后获取的是LoaderManagerImpl对象。
3, 加载原理
异步加载主要分为以下几个步骤,
3.1, initLoader
调用流程图如下,
LoaderManagerImpl的initLoader方法如下,
Callback指继承LoaderCallbacks接口的类对象。
public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {
if (mCreatingLoader) {
throw new IllegalStateException("Called while creating a loader");
}
LoaderInfo info = mLoaders.get(id);
if (DEBUG) Log.v(TAG, "initLoader in " + this + ": args=" + args);
if (info == null) {
// Loader doesn't already exist; create.
info = createAndInstallLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback);
if (DEBUG) Log.v(TAG, " Created new loader " + info);
} else {
if (DEBUG) Log.v(TAG, " Re-using existing loader " + info);
info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback;
}
if (info.mHaveData && mStarted) {
// If the loader has already generated its data, report it now.
info.callOnLoadFinished(info.mLoader, info.mData);
}
return (Loader<D>)info.mLoader;
}
createAndInstallLoader代码如下,
private LoaderInfo createAndInstallLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<Object> callback) {
try {
mCreatingLoader = true;
LoaderInfo info = createLoader(id, args, callback); // 构造LoaderInfo对象
installLoader(info); // 对LoaderInfo进行初始化
return info;
} finally {
mCreatingLoader = false;
}
}
createLoader首先构造一个内部类LoaderInfo对象,然后回调ContactEntryListFragment的onCreateLoader方法创建Loader对象,
实际上是CursorLoader对象。最后将CursorLoader对象作为LoaderInfo对象的mLoader变量。
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类似于一个中间人的角色。
void installLoader(LoaderInfo info) {
mLoaders.put(info.mId, info);
if (mStarted) {
// The activity will start all existing loaders in it's onStart(),
// so only start them here if we're past that point of the activitiy's
// life cycle
info.start();
}
}
LoaderInfo的start方法如下,
void 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;
}
mStarted = true;
if (DEBUG) Log.v(TAG, " Starting: " + this);
if (mLoader == null && mCallbacks != null) {
mLoader = mCallbacks.onCreateLoader(mId, mArgs);
}
if (mLoader != null) {
if (mLoader.getClass().isMemberClass()
&& !Modifier.isStatic(mLoader.getClass().getModifiers())) {
throw new IllegalArgumentException(
"Object returned from onCreateLoader must not be a non-static inner member class: "
+ mLoader);
}
if (!mListenerRegistered) { // 是否注册
mLoader.registerListener(mId, this);
mLoader.registerOnLoadCanceledListener(this);
mListenerRegistered = true;
}
mLoader.startLoading();
}
}
initLoader方法第一步主要是创建LoaderInfo对象,回调ContactEntryListFragment的onCreateLoader方法创建Loader对象, 以及对LoaderInfo的变量状态赋值。
3.2, startLoading
流程图如下,
2个注册监听方法在后面再论述,先论述startLoading方法,到此,开始异步加载了。
开始几个方法兜兜转转,最后会调用onForceLoad方法,该方法如下,
protected void onForceLoad() {
super.onForceLoad();
cancelLoad();
mTask = new LoadTask();
if (DEBUG) Log.v(TAG, "Preparing load: mTask=" + mTask);
executePendingTask();
}
LoadTask继承AsyncTask类,重写了
doInBackground/ onPostExecute/ onCancelled等方法。
executePendingTask方法如下,
void executePendingTask() {
if (mCancellingTask == null && mTask != null) {
if (mTask.waiting) {
mTask.waiting = false;
mHandler.removeCallbacks(mTask);
}
if (mUpdateThrottle > 0) {
long now = SystemClock.uptimeMillis();
if (now < (mLastLoadCompleteTime+mUpdateThrottle)) {
// Not yet time to do another load.
if (DEBUG) Log.v(TAG, "Waiting until "
+ (mLastLoadCompleteTime+mUpdateThrottle)
+ " to execute: " + mTask);
mTask.waiting = true;
mHandler.postAtTime(mTask, mLastLoadCompleteTime+mUpdateThrottle);
return;
}
}
if (DEBUG) Log.v(TAG, "Executing: " + mTask);
mTask.executeOnExecutor(mExecutor, (Void[]) null);
}
}
直接调用LoadTask的executeOnExecutor方法开始异步查询。
mExecutor变量在构造方法中赋值为AsyncTask.THREAD_POOL_EXECUTOR。
关于这个THREAD_POOL_EXECUTOR线程池以及AsyncTask原理在此就不论述了。
private final Executor mExecutor;
public AsyncTaskLoader(Context context) {
this(context, AsyncTask.THREAD_POOL_EXECUTOR);
}
/** {@hide} */
public AsyncTaskLoader(Context context, Executor executor) {
super(context);
mExecutor = executor;
}