ViewModel简单解析
为什么使用ViewModel
进行Android开发一段时间后,大多数人会发现Activity承载着繁多的任务,数据储存,ui控制都是它。其中数据存储是重中之重,当屏幕发生旋转,Activity改变大小时,在不做任何配置下,Activity会进行recreate,之前的数据没了。当然,自己可以手动进行在onConfigurationChanged对数据进行处理,除此之外,数据根据Activity/Fragment的生命周期处理也是繁琐的地方,出现的MVP等MVVM都是对此进行的解决方案,而我认为,MVP使用过于繁琐让人捉摸不透,那么MVVM才是当前解决数据分离的最佳方案。
前置知识
LifeCycle LiveData Kotlin Kotlin-Coroutines
使用
|
|
初探ViewModel
可以看到ViewModel只是一个抽象类,我们平时使用都不会是直接new出来的,都是通过ViewModelProviders构造出的一个ViewModel实例。类里没多少东西,mBagOfTags对象和clear()方法比较令人在意,明显是当ViewModel要被清除的时候所做的工作,我们下面直接看一开始调用的ViewModelProviders。
|
|
看到of()方法就是我们调用链的第一条,其中ViewModelProviders把真正的Provider委托给了ViewModelProvider(注意没有s),进阶一点的ViewModel用法是可以自己定义factory去生成我们的ViewModel实例的,明显的是如果我们不传自己的factory也需要一个默认的AndroidViewModelFactory去帮助我们构建。
|
|
AndroidViewModelFactory是ViewModelProvider的内部类,create()方法通过传进来的ModelClass反射构建我们需要的ViewModel实例。
|
|
在ViewModelProvider中,我们看到了熟悉的get()方法,这里利用拿到的ViewModelStore转成我们实际调用到的ViewModel实例,而且会确保这个ViewModel实例是一个单例,那么ViewModelStore从何而来呢?正是上面ViewModelProviders的of()方法中Fragment/FragmentActivity中储存的ViewModelStore,这个ViewModelStore实际上是一个HashMap。这不是又把ViewModel放在Activity/Fragment?实际上他们自有处理。
|
|
可以看到在onCreate()方法里会获取上一次的NonConfigurationInstances,当然前提是要有,onRetainNonConfigurationInstance储存了当前保存的ViewModel。
|
|
诶?这不是跟网文说的用Fragment储存状态不一样吗?因为这是AndroidX转换后的实现,传说中的Fragment大法是在AndroidX转换前中实现的。
其中of()方法的返回值变成了在holderfragment持有的viewModelStore,由于实现都使用的是这个holderfragment,这里也就不需要ViewModelProvider来区分Activity与Fragment,去获取他们自己持有的ViewModelStore。
|
|
之所以会用到Fragment大法,是因为在Fragment中有一个setRetainInstance()的方法,在Activity重新创建的时候,可以跳过onDestroy()的生命周期,直接Detach掉(注意此时Fragment并未销毁),重新创建Activity的时候还可以重新Attach(注释及源码均来自SDK29),很好的利用了Fragment的这一特性。
|
|
When ViewModel onClear
还记的开头提到的mBagOfTags对象和clear()方法吗?我们知晓了ViewModel是如何实例化并使用,那么反过来也需要知道ViewModel是如何清除的,我们从ViewModel-ktx的包可以知道,对于清除ViewModel任务,使用了kotlin的扩展,将所有将要被取消的任务丢进协程里进行取消,并且是在主线程完成的。
|
|
延迟委托
在ktx包另一个名为ViewModelProvider.kt的文件中,我们实际上使用的get()方法是具有延迟的委托属性,这里如果没有创建对应的ViewModel,这里会传入类型为Factory的factoryProducer对象进行创建,如果存在,这里还会检查一下缓存,真没有的话还会用类型为ViewModelStore的storeProducer的对象找是否有存储这个ViewModel。
|
|