Android 3.0 中引入了加载器,支持轻松在 Activity 或片段中异步加载数据。 我们今天就来八一八里面的具体流程。
初始化和开始
我们可以看到LoaderManager是一个抽象类,通过FragmentActivity.getSupportLoaderManager()获取实现类,中间用了多次代理,在FragmentHostCallback里获取实现类LoaderManagerImpl。
LoaderManagerImpl getLoaderManagerImpl() {
if (mLoaderManager != null) {
return mLoaderManager;
}
mCheckedForLoaderManager = true;
mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true /*create*/);
return mLoaderManager;
}
如果mLoaderManager不存在,则进行创建,mCheckedForLoaderManager作为检测是否已经创建LoaderManager的标志,在之后的doLoaderStart里使用。
void doLoaderStart() {
if (mLoadersStarted) {
return;
}
mLoadersStarted = true;
if (mLoaderManager != null) {
mLoaderManager.doStart();
} else if (!mCheckedForLoaderManager) {
mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false);
// the returned loader manager may be a new one, so we have to start it
if ((mLoaderManager != null) && (!mLoaderManager.mStarted)) {
mLoaderManager.doStart();
}
}
mCheckedForLoaderManager = true;
}
如果为mCheckedForLoaderManager = false,则创建LoaderManager。
LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {
if (mAllLoaderManagers == null) {
mAllLoaderManagers = new SimpleArrayMap<String, LoaderManager>();
}
LoaderManagerImpl lm = (LoaderManagerImpl) mAllLoaderManagers.get(who);
if (lm == null) {
if (create) {
lm = new LoaderManagerImpl(who, this, started);
mAllLoaderManagers.put(who, lm);
}
} else {
lm.updateHostController(this);
}
return lm;
}
我们可以看到,LoaderManagerImpl会先从SimpleArrayMap里面取,如果有则更新HostController,否则创建LoaderManagerImpl,并且保存在SimpleArrayMap。接下来我们来看看初始化和加载Loader。
mLoaderManager.initLoader(0, null, this);
public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {
......//省略
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 {
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;
}
首先我们看到的是Loader的包装类LoaderInfo,里面包含id,Loader和对Loader的处理,这个暂时略过,后面会提到。先根据id从mLoaders取出LoaderInfo,如果不存在则创建并且加载Loader,否则就更新mCallbacks,如果LoaderInfo有数据并且处于开始状态,则回调加载数据结束callOnLoadFinished,返回Loader。
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;
}
}
private LoaderInfo createLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<Object> callback) {
LoaderInfo info = new LoaderInfo(id, args, callback);
Loader<Object> loader = callback.onCreateLoader(id, args);
info.mLoader = loader;
return info;
}
创建LoaderInfo,在这里我们就能看到回调的onCreateLoader获取Loader,然后赋值给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放在mLoaders里以备之后使用,如果处于开始状态,则进行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();
}
}
如果处于保留状态,并且保留时处于开始状态或者,则不需要做任何事情,如果处于开始状态,也不需要做任何事情。看到这里,细心的读者可能会感到奇怪,前面明明是判断mStarted = true,然后进行start,但如果判断mStarted = true,则不做任何事情,其实前一个mStarted是LoaderManagerImpl的变量,判断LoaderManagerImpl是否处于开始状态,则后一个mStarted是LoaderInfo的变量,判断LoaderInfo是否处于开始状态,两个mStarted并不相同。如果mLoader为null,则进行创建,判断Loader是否是非静态内部成员类,如果是则抛出异常,如果之前监听器没有注册,则进行注册,然后startLoading回调onStartLoading,至此完成initLoader。
停止和销毁
当Activity或者Fragment被销毁时,Loader也会被销毁,让我们根据代码一探真相。
@Override
protected void onDestroy() {
......//省略
doReallyStop(false);
mFragments.dispatchDestroy();
mFragments.doLoaderDestroy();
}
在这里我们可以看出,Loader先Stop,然后Destroy。
void doReallyStop(boolean retaining) {
if (!mReallyStopped) {
......//省略
onReallyStop();
}
}
void onReallyStop() {
mFragments.doLoaderStop(mRetaining);
mFragments.dispatchReallyStop();
}
void doLoaderStop(boolean retain) {
......//省略
if (retain) {
mLoaderManager.doRetain();
} else {
mLoaderManager.doStop();
}
}
void doStop() {
......//省略
for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).stop();
}
mStarted = false;
}
前面都是一系列的调用,这里开始对Loaders进行stop。
void stop() {
......//省略
if (!mRetaining) {
if (mLoader != null && mListenerRegistered) {
// Let the loader know we're done with it
mListenerRegistered = false;
mLoader.unregisterListener(this);
mLoader.unregisterOnLoadCanceledListener(this);
mLoader.stopLoading();
}
}
}
取消监听,开始stop,然后我们回到Activity.onDestroy(),继续看如何进行。destroy
void doLoaderDestroy() {
......//省略
mLoaderManager.doDestroy();
}
void doDestroy() {
if (!mRetaining) {
if (DEBUG) Log.v(TAG, "Destroying Active in " + this);
for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).destroy();
}
mLoaders.clear();
}
if (DEBUG) Log.v(TAG, "Destroying Inactive in " + this);
for (int i = mInactiveLoaders.size()-1; i >= 0; i--) {
mInactiveLoaders.valueAt(i).destroy();
}
mInactiveLoaders.clear();
}
对mLoaders和mInactiveLoaders依次进行destroy,并且进行清空。
void destroy() {
......//省略
if (mCallbacks != null && mLoader != null && mHaveData && needReset) {
......//省略
try {
mCallbacks.onLoaderReset(mLoader);
} finally {
if (mHost != null) {
mHost.mFragmentManager.mNoTransactionsBecause = lastBecause;
}
}
}
......//省略
if (mLoader != null) {
if (mListenerRegistered) {
mListenerRegistered = false;
mLoader.unregisterListener(this);
mLoader.unregisterOnLoadCanceledListener(this);
}
mLoader.reset();
}
if (mPendingLoader != null) {
mPendingLoader.destroy();
}
}
重置Loader状态,完成destroy
至此我们看完了Loader初始化,开始,停止和销毁整个过程,除此之外还有当手机横竖屏切换过程的状态处理,因为比较简单,就不再复述了,感兴趣的读者可以自己看下。
总结
Loader的好处是和Activity,Fragment生命周期绑定,调用者无需关心,监控其数据源并在内容变化时传递新结果。但个人感觉略显复杂,没带来太多的方便,大家可以留言一起探讨下。
参考资料
欢迎关注我的微博