前言
最近一个月主要实现了IM功能,其中UI框架使用了ViewModel和LiveData的存储和通知机制,实现后代码简洁易于维护。
感慨于Android arch components控件强大同时,需要顺带分析一波其中源码实现。今天先来分析一下ViewModel的源码实现。
ViewModel简介
ViewModel是通过关联生命周期的方式来存储和管理跟UI相关的数据。即使configuration发生变化,在ViewModel中存放的数据是不会被销毁的。
没使用ViewModel的时候,如果系统Configuration发生变化,我们的Activity会被销毁重建,导致Activity中的UI数据丢失。为了规避这个问题,我们只能在onSaveInstanceState()将UI数据进行保存,在onCreate方法中判断savedInstanceState中是否有我们存储的数据。
有了ViewModel之后,我们只需要将数据存储到ViewModel即可,ViewModel中的数据不会随着Activity的销毁重建而消失。同时,如果不同的Fragment使用相同的Activity对象来获取ViewModel,可以轻易的实现数据共享和通信。
使用ViewModel的例子:
// 自定义一个ViewModel,存储一个字符串
public class TestViewModel extends ViewModel {
public String content;
@Override
protected void onCleared() {
// 数据清理工作
content = null;
}
}
// 在Activity中获取并使用ViewModel
TestViewModel viewModel = ViewModelProviders.of(activity).get(TestViewModel.class);
Log.d("tag", viewModel.content);
三个问题
- ViewModel是如何创建出来的?
- 为什么不同的Fragment使用相同的Activity对象来获取ViewModel,可以轻易的实现ViewModel共享?
- ViewModel为什么在Activity销毁重建时不会被销毁回收?
我个人习惯,看源码时候总是要带着问题去分析理解,这样才会有所收获。
源码分析
ViewModel是如何创建出来的?
通过示例代码,去掉链式调用后,我们可以看到ViewModel是通过如下两步创建出来的:
// 1. 创建ViewModelProvider
ViewModelProvider viewModelProvider = ViewModelProviders.of(activity);
// 2. 通过反射获取ViewModel
TestViewModel viewModel = viewModelProvider.get(TestViewModel.class);
创建ViewModelProvider
先看下第一步的源码实现:
public static ViewModelProvider of(@NonNull FragmentActivity activity, @Nullable Factory factory) {
if (factory == null) {
// 如果传入的对象创建工厂类为null,则使用默认的AndroidViewModelFactory来创建对象
factory = AndroidViewModelFactory.getInstance(application);
}
// 创建一个ViewModelProvider
return new ViewModelProvider(ViewModelStores.of(activity), (Factory)factory);
}
源码中,我们发现创建一个ViewModelProvider需要传入两个参数:ViewModelStore和Factory。我们先看下Factory的实现。
Factory
Factory顾名思义,定义了创建ViewModel的行为接口。里面只有一个create方法,用于子类自行决定如何实现一个ViewModel对象的创建。
public interface Factory {
<T extends ViewModel> T create(@NonNull Class