【Android Jetpack】- ViewModel(源码分
简介
ViewModel类旨在以生命周期感知的方式存储和管理与UI相关的数据。
使用场景1
- 定义ViewModel类
class ViewModelData : ViewModel(){
private val viewModel : VMData by lazy {
VMData().also {
it.age = 26
it.name = "丘比特"
}
}
}
class VMData{
var name = ""
var age = 21
}
- 使用ViewModelProvider创建ViewModel对象
val vmData = ViewModelProvider.AndroidViewModelFactory(application).create(ViewModelData::class.java)
// 这个区别是AndroidViewModelFactory是单例
val vmData1 = ViewModelProvider.AndroidViewModelFactory.getInstance(application).create(ViewModelData::class.java)
这是最基本的时候方式,使用ViewModelProvider来提供ViewModel对象。通过查看源码可以得知。这种方式每使用一次就会产生一个ViewModel对象。
这样看上去ViewModel的用处并不是很大,根据官网的建议,我们可以把加载数据的逻辑放在ViewModel里面,替代以前的Loaders模块。
-
不使用ViewModel
屏幕快照 2019-10-20 下午8.58.50.png -
使用ViewModel
屏幕快照 2019-10-20 下午8.58.56.png
使用场景2 — Fragment之间的数据共享
通过查看ViewModelProvider源码,发现ViewModelProvider可以通过get方法来获取ViewModel。
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
return (T) viewModel;
} else {
...
}
...
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
} else {
viewModel = (mFactory).create(modelClass);
}
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
如果想不同Fragment直接拿到是相同的ViewModel,那么就得保证mViewModelStore唯一,mViewModelStore是ViewModelStore实例,源码很简单,自行查看。
- 使用
class ViewModelActivity: AppCompatActivity(){
...
// Fragment直接的数据共享
private fun fragmentShare(){
val vm = ViewModelProvider(this).get(ViewModelData::class.java)
// ViewModelProviders已经被抛弃
val vm1 = ViewModelProviders.of(this)[ViewModelData::class.java]
}
}
看一下构造体
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
owner就是AppCompatActivity对象,而AppCompatActivity实现了HasDefaultViewModelProviderFactory和ViewModelStoreOwner接口。那这里得到的Factory和ViewModelStore就是AppCompatActivity返回的。
public ViewModelStore getViewModelStore() {
...
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
...
if (mDefaultFactory == null) {
mDefaultFactory = new SavedStateViewModelFactory(
getApplication(),
this,
getIntent() != null ? getIntent().getExtras() : null);
}
return mDefaultFactory;
}
如果是同一个AppCompatActivity,那么Factory和ViewModelStore便是唯一的,自然就可以在Fragment之间共享数据了。
使用场景3 - 状态的备份和恢复
如“保存UI状态”文章中所述,ViewModel对象可以处理配置更改,因此您不必担心轮换或其他情况下的状态。但是,如果需要处理系统启动的进程终止,则可能要使用onSaveInstanceState作为备份。
在场景2中,创建的ViewModelProvider是一个SavedStateViewModelFactory对象,那么我们来看看SavedStateViewModelFactory实现了什么功能。SavedStateViewModelFactory继承了AbstractSavedStateViewModelFactory抽象类,所以这里集中分析这两个类。
-
AbstractSavedStateViewModelFactory
改类主要有三个变量private final SavedStateRegistry mSavedStateRegistry; private final Lifecycle mLifecycle; private final Bundle mDefaultArgs;
SavedStateViewModelFactory构造体
public SavedStateViewModelFactory(@NonNull Application application, @NonNull SavedStateRegistryOwner owner, @Nullable Bundle defaultArgs) { super(owner, defaultArgs); mApplication = application; mFactory = ViewModelProvider.AndroidViewModelFactory.getInstance(application); }
AbstractSavedStateViewModelFactory构造体
public AbstractSavedStateViewModelFactory(@NonNull SavedStateRegistryOwner owner, @Nullable Bundle defaultArgs) { mSavedStateRegistry = owner.getSavedStateRegistry(); mLifecycle = owner.getLifecycle(); mDefaultArgs = defaultArgs; }
mSavedStateRegistry,mLifecycle都是AppCompatActivity对象返回,mDefaultArgs是AppCompatActivity的持有的Bundle对象。mFactory是ViewModelProvider.AndroidViewModelFactory单例。
-
创建ViewModel 对象
调用AbstractSavedStateViewModelFactory的create方法public final <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) { // 消耗先前提供的保存状态,之前存储的Bundle对象 Bundle restoredState = mSavedStateRegistry.consumeRestoredStateForKey(key); // 将之前的保存状态和现在进行合并,放到SavedStateHandle中的一个数组里 SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, mDefaultArgs); // 创建持有key和handle的SavedStateHandleController对象 SavedStateHandleController controller = new SavedStateHandleController(key, handle); // 添加监听和注册SavedStateProvider到SavedStateRegistry里 controller.attachToLifecycle(mSavedStateRegistry, mLifecycle); // 创建viewmodel对象 T viewmodel = create(key, modelClass, handle); // 保存controller到viewmodel实例中 viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller); // 创建拥有组件重新启动时执行类的对象 mSavedStateRegistry.runOnNextRecreation(OnRecreation.class); return viewmodel; }
runOnNextRecreation方法
public void runOnNextRecreation(@NonNull Class<? extends AutoRecreated> clazz) { ... if (mRecreatorProvider == null) { mRecreatorProvider = new Recreator.SavedStateProvider(this); } ... mRecreatorProvider.add(clazz.getName()); }
SavedStateProvider构造体
SavedStateProvider(final SavedStateRegistry registry) { registry.registerSavedStateProvider(COMPONENT_KEY, this); }
向SavedStateRegistry对象注册直接,key = COMPONENT_KEY。
-
AppCompatActivity调用
protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mSavedStateRegistryController.performRestore(savedInstanceState); ... }
protected void onSaveInstanceState(@NonNull Bundle outState) { ... mSavedStateRegistryController.performSave(outState); }
-
SavedStateRegistryController
public void performRestore(@Nullable Bundle savedState) { Lifecycle lifecycle = mOwner.getLifecycle(); ... lifecycle.addObserver(new Recreator(mOwner)); mRegistry.performRestore(lifecycle, savedState); } public void performSave(@NonNull Bundle outBundle) { mRegistry.performSave(outBundle); }
-
使用
定义ViewModelclass SavedStateViewModel(private val state: SavedStateHandle) : ViewModel(){ private val viewModel : VMData by lazy { VMData().also { it.age = 26 it.name = "丘比特" } } }
-
创建ViewModel
private fun savedStateModel(){ val vm = ViewModelProvider(this, SavedStateViewModelFactory(application,this)).get(SavedStateViewModel::class.java) val vm1 = ViewModelProvider(this, defaultViewModelProviderFactory).get(SavedStateViewModel::class.java) }
-