众所周知,ViewModel的作用在于以可感知生命周期的方式存储与管理UI相关的数据,它允许数据在例如屏幕旋转这样的配置发生变化时得以保存,那系统又是如何做到保存ViewModel的呢,让我们从源码中去溯本追源吧。
AndroidX支持库中的AppCompatActivity继承自FragmentActivity,而后者又继承自ComponentActivity,ComponentAcitivty实现了ViewModelStoreOwner接口,该接口定义如下:
很显然,实现该接口的类需要能够提供一个ViewModelStore,而ViewModelStore即为用于存储ViewModel对象的仓库,其内部通过一个HashMap管理ViewModel。
当需要获取ViewModel时,需先创建ViewModelProvider实例,在2.2.0版本的ViewModel库中,不再通过ViewModelProvider的静态of方法获取实例,而需要通过ViewModelProvider的构造函数去创建实例,其存在如下构造函数:



那么这个NonConfigurationInstances又是从何而来的呢,通过方法跟踪,可找到其在Activity的attach方法中通过方法参数传入
@UnsupportedAppUsage
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, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
……
mLastNonConfigurationInstances = lastNonConfigurationInstances;
……
}
Activity的attach方法是在Activity的加载流程中由ActivityThread的performLaunchActivity调用的,调用时传入的是ActivityRecordClient中的NonConfigurationInstances对象,那ActivityRecordClient又是在什么时候保存的NonConfigurationInstances对象的呢,这就要从Activity因为配置变化被销毁时查起了。
当Activity因为配置变化被销毁时,在其销毁流程中ActivityThread会调用performDestroyActivity方法,该方法内部会回调Activity的retainNonConfigurationInstances方法获取NonConfigurationInstances并保存在ActivityRecordClient中以备之后Activity重建之需,以下是retainNonConfigurationInstances方法的部分流程:
NonConfigurationInstances retainNonConfigurationInstances() {
Object activity = onRetainNonConfigurationInstance();
……
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.activity = activity;
……
return nci;
}
其中onRetainNonConfigurationInstance()方法由ComponentActivity进行了覆写:

onRetainNonConfigurationInstances方法的主要逻辑就是创建了一个NonConfigurationInstances对象(此NonConfigurationInstances类与前头的NonConfigurationInstances类不是同一个类),并将当前Activity的ViewModelStore保存到了所创建的对象的viewModelStore变量中,从而使得Activity在销毁后重建时能获取到销毁前的ViewModelStore,进而可获取到销毁前的ViewModel。onRetainNoConfigurationInstance方法返回的NonConfigurationInstance对象最终被存储到了retainNonConfigurationInstances方法中创建的NonConfigurationInstances对象的activity变量里。

网友评论