viewmodel的存取流程
一:获取view model的代码
publicextends ViewModel> T get(@NonNull String key, @NonNull Class modelClass) { ViewModel viewModel = mViewModelStore.get(key);//从一个hash map中用key取view model,key是view model的类名。 if (modelClass.isInstance(viewModel)) {//如果还没有view model实例,即上一步得到null, 那么就不会进去,如果进入了,就会返回view mdoel了 if (mFactory instanceof OnRequeryFactory) { ((OnRequeryFactory) mFactory).onRequery(viewModel); } return (T) viewModel; //返回view model } else { //noinspection StatementWithEmptyBody if (viewModel != null) { // TODO: log a warning. } } if (mFactory instanceof KeyedFactory) { viewModel = ((KeyedFactory) mFactory).create(key, modelClass);//创建view model } else { viewModel = mFactory.create(modelClass);//创建view model } mViewModelStore.put(key, viewModel);//往map里面插入这个view model return (T) viewModel; }
activity实现了view model store owner,拥有view model store,view model store则拥有一个map存放view model。
但是当配置更改时,view model store实例如何才能保证是旧的那个呢?
二:如何不改变view model store
首先来看看activity如何获取view model store
public ViewModelStore getViewModelStore() { if (getApplication() == null) { throw new IllegalStateException("Your activity is not yet attached to the " + "Application instance. You can't request ViewModel before onCreate call."); }//忽略 if (mViewModelStore == null) { NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance();//这个重点 if (nc != null) { // Restore the ViewModelStore from NonConfigurationInstances mViewModelStore = nc.viewModelStore; } if (mViewModelStore == null) { mViewModelStore = new ViewModelStore(); } } return mViewModelStore; }
因为activity创建时view model store都是null,当我们第一次取时,会看看nc,如果nc不为null,代表nc存有以前的view model,就取出来就行了,没有就创建。
所以关键是,这个nc是什么,它是如何保存我们之前的viewmodel的,为森马它不为空,就存有旧 viewmodel呢?
搞明白这个nc,就知道view mdoel store是如何不变的了。
三:搞明白NonCon.....Instances如何存
在上一段代码中,ComponenetActivity.java的getViewModelStore方法会调用Activity.java的getLastNCI方法,getLastNCI方法会返回Activity.java内部的一个NCI对象
static final class NonConfigurationInstances { Object activity; 。。。。。 }
那为什么这个对象会存有我们的viewmdoelstore实例呢?
原因就是:
当Activity.java销毁的时候,会保存Activity.NCI实例:
Activity,java NonConfigurationInstances retainNonConfigurationInstances() { Object activity = onRetainNonConfigurationInstance(); ...... NonConfigurationInstances nci = new NonConfigurationInstances(); nci.activity = activity; return nci; } ComponentActivity.java public final Object onRetainNonConfigurationInstance() { ViewModelStore viewModelStore = mViewModelStore; ...... NonConfigurationInstances nci = new NonConfigurationInstances(); nci.viewModelStore = viewModelStore; return nci; }
activity销毁的时候,系统会调用retainXXXX,然后调用 onRetainXXXX,把view model store存进去了,把ComponentActivity.java的NCI对象存到Activity.java的NCI对象的一个叫做“activity”的变量里面,这个变量名十分误导人,叫其他不好吗?叫store也好啊!!
四:搞明白NonCon.....Instances如何恢复
系统调用Activity.java的attach方法
Activity.java final void attach( NonConfigurationInstances lastNonConfigurationInstances){ ... mLastNonConfigurationInstances = lastNonConfigurationInstances ... }
这样呢,在第二部分 ComponentActivity.java获取viewmdoelstore的方法里就可以获取到这个NCI了。
整体流程如下
参考:https://blog.mindorks.com/android-viewmodels-under-the-hood