- 前言
- 一、ViewModel使用
- 1、定义ViewModel
- 2、创建ViewModel
- 二、源码分析
- 1、创建流程
- ViewModelStore
- ViewModelProvider.NewInstanceFactory()
- get(MyViewModel::class.java)
- 2、Activity重建
- 3、ViewModel生命周期
ViewModel组件的作用就是保证数据的稳定性。当我们在某Activity输入100个字段以后,发生横竖屏切换,Activity重建,此时数据会保存在ViewModel中,Activity重建后再从ViewModel取值即可,ViewModel的生命周期很长,数据不会丢失,配合DataBinding、LiveData使用会更方便。
需要注意的是,ViewModel只是Jetpack中的一个组件库,和MVVM中的ViewModel层是两个概念。
一、ViewModel使用 1、定义ViewModelclass MyViewModel : ViewModel() {
var number : Int = 0
}
如果我们需要使用Application上下文可以继承AndroidViewModel,ViewModel中是不能持有Activity上下文的,因为ViewModel的生命周期比Activity更长,会造成内存泄漏。
我们这里简单定义一个变量number,在Activity中来修改和观测它的值。
class MainActivity : AppCompatActivity() {
private lateinit var myViewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
myViewModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory())
.get(MyViewModel::class.java)
text_number.text = "${myViewModel.number}"
btn_plus.setOnClickListener {
text_number.text = "${++myViewModel.number}"
}
}
}
点击按钮修改ViewModel中number变量的值,横竖屏切换后,Activity重建,number值没变。这样,不需要添加任何保存的代码就保证了数据的稳定。
二、源码分析 1、创建流程 ViewModelStore新版本的ViewModel使用ViewModelProvider来创建ViewModel,第一个参数是环境,ComponentActivity实现了ViewModelStoreOwner接口,这里第一个参数实际传入的就是ViewModelStoreOwner,包含getViewModelStore()方法返回一个ViewModelStore。
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
LifecycleOwner,
ViewModelStoreOwner,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner {
...
}
public interface ViewModelStoreOwner {
@NonNull
ViewModelStore getViewModelStore();
}
ViewModelStore源码也非常简单,只是一个单纯的存储类,提供了get、put、clear等方法
public class ViewModelStore {
private final HashMap mMap = new HashMap<>();
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
final ViewModel get(String key) {
return mMap.get(key);
}
Set keys() {
return new HashSet<>(mMap.keySet());
}
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
ViewModelProvider.NewInstanceFactory()
工厂模式,依赖倒置原则,通过反射来实例化传入的自定义ViewModel类
public static class NewInstanceFactory implements Factory {
public T create(@NonNull Class modelClass) {
try {
return modelClass.newInstance();
} catch (InstantiationException e) {
...
}
}
}
get(MyViewModel::class.java)
查看ViewModelStore有没有此ViewModel,如果有,直接返回,没有则通过工厂来创建并保存入ViewModelStore。
public2、Activity重建T get(@NonNull String key, @NonNull Class modelClass) { ViewModel viewModel = mViewModelStore.get(key); if (modelClass.isInstance(viewModel)) { //noinspection unchecked 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; }
通过查看ComponentActivity源码,当Activity重建后,会执行onRetainNonConfigurationInstance方法,AMS保存的数据,当mViewModelStore为空时,可以从NonConfigurationInstances中重新拿到mViewModelStore,当mViewModelStore不为空,getViewModelStore方法就会返回当前的mViewModelStore用于数据的恢复
public final Object onRetainNonConfigurationInstance() {
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;
if (viewModelStore == null) {
// No one called getViewModelStore(), so see if there was an existing
// ViewModelStore from our last NonConfigurationInstance
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
viewModelStore = nc.viewModelStore;
}
}
if (viewModelStore == null && custom == null) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = viewModelStore;
return nci;
}
public ViewModelStore getViewModelStore() {
...
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;
}
3、ViewModel生命周期
网上有一张很经典的图,是说ViewModel的生命周期很长,比Activity的生命周期要长
其实,关于ViewModel的生命周期可以从ComponentActivity的构造方法中看到这样一段代码
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
只有Activity在ON_DESTROY状态,并且通过这个判断isChangingConfigurations,是真正的被销毁了之后,mViewModelStore才会被清空。这里的状态又用到了Lifecycle的状态,可以看到Lifecycle在整个Jetpack组件当中的重要地位,关于Lifecycle状态和事件之间的关系,在我上一篇文章中有介绍。
到此,ViewModel组件的主线流程就看完了,核心就是mViewModelStore存储以及nc恢复,同时通过Lifecycle来控制销毁。



