ViewModel简介
1. Activity或Fragment有自己的生命周期被Framework所管理,Framework可能会根据用户的一些操作以及设备的状态对Actvity或Fragment进行销毁和重建。伴随着Activity或Fragment的销毁和重建,它们当中的数据也会随着一起销毁和重建。对于一些简单的数据,Activity可以使用onSaveInstanceState()方法,并从onCreate的bundle中重新获取,但这一方法仅仅适合一些简单的UI状态,对于列表型这种庞大的数据类型并不适合。
2. Activity或Fragment经常会做一些异步的耗时操作,需要管理这些异步操作得到的数据,并在destroyed的时候清理它们,从而避免内存溢出这类问题的发生。管理数据的成本较大,另外configurationChanged发生时,部分资源和数据需要重新请求,降低了性能。
3. Activity或Fragment本身需要处理很多用户的输入事件并和操作系统相关操作们,如果还维护管理业务数据和资源,会导致Activity和Fragment过于庞大。
特点
以关联生命周期的方式来存储和管理UI相关的数据,即使configuration发生改变(比如旋转屏幕,系统语言字体变化),数据仍然可以存在不会销毁。
Activity和Fragment之间,多个Fragment之间共享数据,轻松解决Activity和Fragment之间数据通信提高复杂性问题。
职责
ViewModel
ViewModel 对象为特定的界面组件提供数据,并包含数据处理业务逻辑,以与模型进行通信。
ViewModel被更换或者清除时,通过onCleard释放持有资源。
ViewModelStore
负责缓存ViewModel,通过clear释放ViewModel持有资源。
ViewModelStoreOwner
负责持有ViewModelStore,Support Library 28中Fragemnt,Activity和HoldFragment是ViewModelStoreOwner的具体实现类,他们内部持有ViewModelStore。
ViewModelStores
负责通过Activity或者Fragment获取ViewModelStore。
1. 如果Activity或者Fragment已实现ViewModelStoreOwner接口,直接返回内部ViewModelStore;
2. 如果Activity或者Fragment未实现ViewModelStoreOwner接口,通过HoldFragment机制获得ViewModelStore;
ViewModelProvider
负责获取ViewModel实例,构造ViewModelProvider需要ViewModelStore和Factory。
1. 根据ViewModel Class名称,从ViewModelStore缓存中获取ViewModel实例;
2. 步骤1获取成功,直接返回实例;
3. 步骤1获取失败,通过Factory反射构造ViewModel,内置Factory有NewInstanceFactory,AndroidViewModelFactory。
4. 使用ViewModelStore缓存步骤3创建的ViewModel实例后,返回ViewModel实例。
ViewModelProviders
负责为Activity和Fragment创建ViewModelProvider。
源码解析
使用
在Activity或者Fragment中获得ViewModel实例。
class MainFragment : Fragment() {
companion object {
fun newInstance() = MainFragment()
}
private lateinit var viewModel: MainViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View {
return inflater.inflate(R.layout.main_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
}
}
上面的样例代码中使用最简单的方式构造ViewModel,通过ViewModelProvider内部自动构造ViewModel,如果需要把Repository等其他对象内置到ViewModel中,可以自定义Factory去实现。这篇文章主要是分析ViewModel内部实现机制,不对ViewModel的构造太多介绍,可以参见android-architecture-components-BasicSample。
关键源码分析
相关源码中比较关键是的ViewModelStores,HoldFragment。
ViewModelStores
public class ViewModelStores {
private ViewModelStores() {
}
public static ViewModelStore of(@NonNull FragmentActivity activity) {
if (activity instanceof ViewModelStoreOwner) {
return ((ViewModelStoreOwner) activity).getViewModelStore();
}
return holderFragmentFor(activity).getViewModelStore();
}
public static ViewModelStore of(@NonNull Fragment fragment) {
if (fragment instanceof ViewModelStoreOwner) {
return ((ViewModelStoreOwner) fragment).getViewModelStore();
}
return holderFragmentFor(fragment).getViewModelStore();
}
}
- 如果Activity或者Fragment实现ViewModelOwner,直接返回内部的ViewModelStore;
- 否则,通过HoldFragment获得ViewModelStore。
注意:无论哪种方式,都实现了对应Activity或者Fragment只存在一个ViewModelStore,且根据Activity和Fragment生命周期销毁(configurationChanged除外)。
HoldFragment
public class HolderFragment extends Fragment implements ViewModelStoreOwner {
//仅存在一个HolderFragmentManager实例
private static final HolderFragmentManager sHolderFragmentManager = new HolderFragmentManager();
private ViewModelStore mViewModelStore = new ViewModelStore();
public HolderFragment() {
//保留Fragment
setRetainInstance(true);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sHolderFragmentManager.holderFragmentCreated(this);
}
@Override
public void onDestroy() {
super.onDestroy();
mViewModelStore.clear();
}
@Override
public ViewModelStore getViewModelStore() {
return mViewModelStore;
}
public static HolderFragment holderFragmentFor(FragmentActivity activity) {
return sHolderFragmentManager.holderFragmentFor(activity);
}
static class HolderFragmentManager {
private Map mNotCommittedActivityHolders = new HashMap<>();
private Map mNotCommittedFragmentHolders = new HashMap<>();
...
}
1. HoldFragment实现ViewModelStoreOwner接口;
2.setRetainInstance,configurationChanged后,短暂保留Fragment,从而保留ViewModelStore[参考];
3. onDestory时,ViewModelStore clear;
4. sHolderFragmentManager仅存在一个实例;
5. NotCommitted变量和holderFragmentCreated规避为一个Activity或者Fragment创建多个HoldFragment。
Support Library
support v4 28.0.0 中FragmentActivity和Fragment已实现ViewModelStoreOwner接口,不再需要HoldFragment机制支持ViewModel特性。
Fragment
通过在OnDestroy方法对configuration的判断,保留下ViewModelStore。
public class Fragment implements LifecycleOwner, ViewModelStoreOwner {
ViewModelStore mViewModelStore;
public ViewModelStore getViewModelStore() {
if (this.getContext() == null) {
throw new IllegalStateException("Can't access ViewModels from detached fragment");
} else {
if (this.mViewModelStore == null) {
this.mViewModelStore = new ViewModelStore();
}
return this.mViewModelStore;
}
}
public void onDestroy() {
this.mCalled = true;
FragmentActivity activity = this.getActivity();
boolean isChangingConfigurations = activity != null && activity.isChangingConfigurations();
if (this.mViewModelStore != null && !isChangingConfigurations) {
this.mViewModelStore.clear();
}
}
}
FragmentActivity
了解下NonConfigurationInstances,此处不再赘述。
public class FragmentActivity extends SupportActivity implements ViewModelStoreOwner {
private ViewModelStore mViewModelStore;
public ViewModelStore getViewModelStore() {
if (this.getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached to the Application instance. You can't request ViewModel before onCreate call.");
} else {
if (this.mViewModelStore == null) {
FragmentActivity.NonConfigurationInstances nc = (FragmentActivity.NonConfigurationInstances)this.getLastNonConfigurationInstance();
if (nc != null) {
this.mViewModelStore = nc.viewModelStore;
}
if (this.mViewModelStore == null) {
this.mViewModelStore = new ViewModelStore();
}
}
return this.mViewModelStore;
}
}
protected void onCreate(@Nullable Bundle savedInstanceState) {
this.mFragments.attachHost((Fragment)null);
super.onCreate(savedInstanceState);
FragmentActivity.NonConfigurationInstances nc = (FragmentActivity.NonConfigurationInstances)this.getLastNonConfigurationInstance();
if (nc != null && nc.viewModelStore != null && this.mViewModelStore == null) {
this.mViewModelStore = nc.viewModelStore;
}
}
protected void onDestroy() {
super.onDestroy();
if (this.mViewModelStore != null && !this.isChangingConfigurations()) {
this.mViewModelStore.clear();
}
this.mFragments.dispatchDestroy();
}
}
总结
Jetpack中ViewModel的设计和实现并不是很复杂,ViewModel是Google官方推荐MVVM模式实现的重要组成部分,ViewModel与Lifecycle和LiveData等Jetpack组件组合使用会更加发挥其作用,待后续深入分析其他Jetpack组件源码实现。