Loader从android 3.0以后引进来的,由于它可以在后台加载数据,因此对于应用的开发是比较重要的组成部分。正是这个原因,我才觉得有必要好好研究一下Loader一系列相关的东西。
在此之前,我们应该大概了解了Loader的使用,如果不太了解,可参考之前的文章。按照使用惯例,我们总是从Activity或者Fragment中获取LoaderManager来使用。因此,我们就从Activity.java中的LoaderManager开始分析。
先开始看一下Activity.java的onStart()方法:
protected void onStart() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStart " + this);
mCalled = true;
if (!mLoadersStarted) {
mLoadersStarted = true;
if (mLoaderManager != null) {
mLoaderManager.doStart();
} else if (!mCheckedForLoaderManager) {
mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false);
}
mCheckedForLoaderManager = true;
}
getApplication().dispatchActivityStarted(this);
}
mLoaderManager保存的是当前客户端通过方法getLoaderManager()返回的LoaderManager引用,它的赋值如下:
public LoaderManager getLoaderManager() {
if (mLoaderManager != null) {
return mLoaderManager;
}
mCheckedForLoaderManager = true;
mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true);
return mLoaderManager;
}
在onStart()里,如果发现mLoaderManager不为空,说明它已经被用户通过getLoaderManager()创建了,当前用户正在使用这个LoaderManager,那么需要调用它的doStart()方法来启动它。当然如果值为空,那么通过getLoaderManager(String who, boolean started, boolean create)方法来获取这个引用,这个调用其实和LoaderManager的恢复机制有关,其实是获得恢复的LoaderManager引用,关于恢复,本文后面有介绍。注意第3个参数create值为false,说明不会创建新的LoaderManager,它只是去查询获得引用。代码如下:
LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {
if (mAllLoaderManagers == null) {
mAllLoaderManagers = new ArrayMap<String, LoaderManagerImpl>();
}
LoaderManagerImpl lm = mAllLoaderManagers.get(who);
if (lm == null) {
if (create) {
lm = new LoaderManagerImpl(who, this, started);
mAllLoaderManagers.put(who, lm);
}
} else {
lm.updateActivity(this);
}
return lm;
}
最终所有的引用都保存在了mAllLoaderManagers数组中。而在getLoaderManager()中调用的上面的同名方法,第3个参数传的是true,说明是需要创建一个LoaderManager实例的。而用户获得Activity或者Fragment的LoaderManager实例引用都是通过getLoaderManager()来实现的。
mCalled变量:如果你的自定义Activity没有调用super.onStart(),那么你会收到异常SuperNotCalledException的,这个异常是在performStart()抛出的。
其他变量应该不需要解释了。
接着我们看一下performStop()方法,这个方法是由ActivityThread类调用的,也是控制Activity生命周期的类, performXXX()方法会调用onXXX()方法,和Activity的生命周期是对应的方法,这个不难理解它的作用。
final void performStop() {
…….
if (mLoadersStarted) {
mLoadersStarted = false;
if (mLoaderManager != null) {
if (!mChangingConfigurations) {
mLoaderManager.doStop();
} else {
mLoaderManager.doRetain();
}
}
}
……..
}
mChangingConfigurations变量的作用也很简单:如果当前发生了配置变化,比如屏幕方向改变,语言改变等,这个变量就会被置为true,那么我们需要调用LoaderManager.doRetain()方法,表示需要保存当前的loaderManager,在Activity恢复时也要恢复这个LoaderManager。如果Activity的stop不是由于配置变化引起的,那么直接调用LoaderManager的doStop()方法,直接停止当前的LoaderManager。
还有一个与LoaderManager相关的地方就在performDestroy()方法里,如下:
final void performDestroy() {
mDestroyed = true;
mWindow.destroy();
mFragments.dispatchDestroy();
onDestroy();
if (mLoaderManager != null) {
mLoaderManager.doDestroy();
}
}
上面调用mLoaderManager的doDestory()将其销毁了。这个LoaderManager的生命周期算是比较完整了。也许你会问,既然都已经销毁了,在Activity配置变化的时候这个LoadManager也没有保存下来啊,其实在doDestory()的实现里会去判断如果调用了doRetain(),那么就不会真正销毁这个LoaderManager。
当Activity需要重建的时候,必定需要保存mLoaderManager的引用啊,否则如何恢复这个LoaderManager呢,毕竟mLoaderManager = null了啊。其实机关就在方法retainNonConfigurationInstances()里,如下:
NonConfigurationInstances retainNonConfigurationInstances() {
Object activity = onRetainNonConfigurationInstance();
HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
ArrayList<Fragment> fragments = mFragments.retainNonConfig();
boolean retainLoaders = false;
if (mAllLoaderManagers != null) {
// prune out any loader managers that were already stopped and so
// have nothing useful to retain.
final int N = mAllLoaderManagers.size();
LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
for (int i=N-1; i>=0; i--) {
loaders[i] = mAllLoaderManagers.valueAt(i);
}
for (int i=0; i<N; i++) {
LoaderManagerImpl lm = loaders[i];
if (lm.mRetaining) {
retainLoaders = true;
} else {
lm.doDestroy();
mAllLoaderManagers.remove(lm.mWho);
}
}
}
if (activity == null && children == null && fragments == null && !retainLoaders) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.activity = activity;
nci.children = children;
nci.fragments = fragments;
nci.loaders = mAllLoaderManagers;
return nci;
}
看上面的代码,其关键在于变量mAllLoaderManagers。这个变量上面已经介绍过了,它保存了所有Activity中创建的LoaderManager引用,自然也包含了mLoaderManager引用了。这个方法会被ActivityThread类调用,而且早于performDestroy()方法调用。
这个方法会查看mAllLoaderManagers保存的所有引用,如果某个LoaderManagerImpl.mRetaining值为false的话,就会被remove掉。如果配置变化发生的话,mRetaining = true,当然mRetaining这个值是在performStop()中的doRetain()调用来设置的。
当mAllLoaderManagers处理完成后,别忘记将它的引用保存到nci.loaders中去,这样才能真正恢复。下面我们再来看一下它是如何恢复的呢?且看onCreate()方法:
protected void onCreate(Bundle savedInstanceState) {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
if (mLastNonConfigurationInstances != null) {
mAllLoaderManagers = mLastNonConfigurationInstances.loaders;
}
原来mAllLoaderManagers是从mLastNonConfigurationInstances中恢复的,而mLastNonConfigurationInstances的恢复其实是从onAttach()方法中开始的:
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config) {
……
mLastNonConfigurationInstances = lastNonConfigurationInstances;
接下来再看performStart方法:
final void performStart() {
mFragments.noteStateNotSaved();
mCalled = false;
mFragments.execPendingActions();
mInstrumentation.callActivityOnStart(this);
if (!mCalled) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
" did not call through to super.onStart()");
}
mFragments.dispatchStart();
if (mAllLoaderManagers != null) {
final int N = mAllLoaderManagers.size();
LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
for (int i=N-1; i>=0; i--) {
loaders[i] = mAllLoaderManagers.valueAt(i);
}
for (int i=0; i<N; i++) {
LoaderManagerImpl lm = loaders[i];
lm.finishRetain();
lm.doReportStart();
}
}
}
上面的代码通过调用LoaderManager.finishRetain()以及doReportStart()方法来恢复LoaderManager的状态。
好了,以上就是Activity针对LoaderManager的管理,而Loader的管理自然是LoaderManager的事了。从上面的分析可以看出,Activity和LoaderManager的职能划分很清晰,这也大大简化了Loaders的管理。