本文主要从Loader入手, 去分析Loader使用、Loader的源码分析等,主要分为以下四篇:
本文基于原生的 Android8.0源码进行分析。以下是第三篇内容
LoaderManager对Loader的管理
1.Loader的创建
我们在使用LoaderManager/Loader时, 通常都会写这么一行代码:
getLoaderManager().initLoader(0, null, this);
getLoaderManager()在前面讲到了, 就是去得到一个LoaderManager(实际上是一个LoaderManagerImpl):
LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {
if (mAllLoaderManagers == null) {
mAllLoaderManagers = new ArrayMap<String, LoaderManager>();
}
LoaderManagerImpl lm = (LoaderManagerImpl) mAllLoaderManagers.get(who);
if (lm == null && create) {
lm = new LoaderManagerImpl(who, this, started);
mAllLoaderManagers.put(who, lm);
} else if (started && lm != null && !lm.mStarted){
lm.doStart();
}
return lm;
}
我们去看看initLoader:
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 (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 {
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;
}
这里首先看到的是在mLoaders中通过id去查询是否有Loader对象,有则直接复用,没有则创建一个。这里可以初步确定,所有的Loader对象都是存放在mLoaders中的最终返回的是Loader对象是info.mLoader, 而info是通过createAndInstallLoader 创建的一个LoaderInfo对象, 进入这个方法看一看:
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;
}
从这里我们看到,Loader loader = callback.onCreateLoader(id, args), Loader实际上就是我们在callback接口中的onCreateLoader()这个方法中去创建的Loader, 然后将id, args,Loader一起封装进了LoaderInfo这个对象中。
2.Loader的启动及数据加载
在上面提到的createAndInstallLoader方法中,创建好Loader以后,我们看到调用了方法 installLoader(info):
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();
}
}
这里看到,info保存在了mLoaders中。然后进入info.start()方法,关键代码如下:
void start() {
......
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();
}
}
在这个方法中,首先注册了两个Listener, 分别是数据加载完成和取消加载的监听,这个在后面数据加载完成或者取消加载后会用到。 然后调用了startLoading()方法:
public final void startLoading() {
mStarted = true;
mReset = false;
mAbandoned = false;
onStartLoading();
}
然后进入onStartLoading():
/**
* Subclasses must implement this to take care of loading their data,
* as per {@link #startLoading()}. This is not called by clients directly,
* but as a result of a call to {@link #startLoading()}.
*/
protected void onStartLoading() {
}
onStartLoading在Loader中注释子类必须实现, 而AsyncTaskLoader也没实现这个方法, 所以,这也是为什么前面提到我们自定义的Loader如果继承了AsyncTaskLoader必须实现onStartLoading()这个方法的原因。并且,如果需要真正加载数据,在onStartLoading()方法中还必须调用forceLoad()方法, 我们进入forceLoad()看看, 数据开始加载的逻辑:
@Override
protected void onForceLoad() {
super.onForceLoad();
cancelLoad();
mTask = new LoadTask();
if (DEBUG) Log.v(TAG, "Preparing load: mTask=" + mTask);
executePendingTask();
}
这里, 去new了一个LoadTask, 然后执行这个LoadTask, 我们先看看这个LoaderTask:
final class LoadTask extends AsyncTask<Void, Void, D> implements Runnable {
/* Runs on a worker thread */
@Override
protected D doInBackground(Void... params) {
try {
D data = AsyncTaskLoader.this.onLoadInBackground();
return data;
} catch (OperationCanceledException ex) {
if (!isCancelled()) {
throw ex;
}
return null;
}
}
/* Runs on the UI thread */
@Override
protected void onPostExecute(D data) {
try {
AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);
} finally {
mDone.countDown();
}
}
......
}
可以看到继承自AsyncTask, 并实现了Runnable接口, 我们知道AsyncTask主要是用来做异步操作任务的,这里也间接说明了这个数据加载是异步的。在doInBackground方法中调用了onLoadInBackground()方法, 最终调用了我们自己实现的doInBackground()方法,然后返回数据, 而onPostExecute()方法则在数据完成后, 往下分发了数据, 通过调用dispatchOnLoadComplete(), 而前面提到,在info.start()方法中注册了数据完成的监听,这里最终调用了onLoadFinished()方法, 从而把加载完毕的数据回调给了业务逻辑。