什么是viewmodel
- 具备宿主生命周期感知能力的数据存储组件
- viewmode保存的数据,在页面因为配置变更导致页面销毁重建之后依然存在,复用同一个viewmodel实例
viewmodel什么情况下能复用
- 配置变更如:横竖屏切换,分辨率调整,权限变更,系统字体样式
- 如果内存不足,电量不足等系统原因导致页面被回收(savedState的能力)
viewmodel的用法
用法一
这样的viewmodel是可以做到因为系统原因的页面销毁重建,做到数据的保存,实际上是对Viewmodel的复用
class mViewModel:ViewModel() {
val getHttp : MutableLiveData<T>
fun getHttp():LiveData<T>{
// 如果因为配置变更而页面销毁,viewmodel实例被保存下来
// 所以getHttp.value 有值,就可以不发起网络请求了
if(getHttp.value == null){
data = api.getHttp()
getHttp.value = data
}
return getHttp
}
}
class Activity {
mViewModel.getHttp().observer(this,Observer{
// 获取数据
})
}
用法二
这个无论是配置不足还是内存,电量等原因导致页面被回收重建时
无论是不是同一个viewmodel实例都能做到复用
需要引入 api 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0'
class mViewModel(val savedState:SavedStateHandle):ViewModel() {
val getHttp = MutableLiveData<T>()
// 一级页面
fun getHttpData(){
// 有数据就返回,内存级别的复用,都可以不是同一个viewmodel实例
if(getHtt.value == null){
getHttp.value = savedState.get<T>(Key)
return getHttp
}
// 没有数据
val data = api.getHttpData()
// 保存数据
savedState.set(Key,data)
getHttp.value = data
return getHttp
}
}
用法三
跨页面数据共享
class MyApplication:Application(),viewModelStoreOwner {
prvate val appViewModelStore :ViewModelStore by lazy{
ViewModelStore()
}
override fun getViewModelStore(): ViewModelStore {
return appViewModelStore
}
}
// 创建 传applicaiton
val viewmodel = ViewProider(application).get(xxxViewModel::class.java)
viewmodel复用如何实现的?
我们从viewmodel的创建入手
ViewModelProvider(this).get(xxxViewModel::class.java)
先看到ViewModelProvider是接收一个ViewModelStoreOwner和Factory(系统帮我们创建的)
而我们的activity或者Fragment都是实现了ViewModelStoreOwner接口的
重写了getViewModelStore,返回一个ViewModelStore对象,所以可以直接传this
然后将我们传入的两个值ViewModelStore和Factory做了一个保存
而ViewModelStore本质上就是一个HashMap,用来存放我们的ViewModel
再接着看get方法,是先从ViewModelStore去获取viewmodel,没有的话就用Factory去创建
既然ViewModel保存在ViewModelStore,那么只要ViewModelStore存在,viewmodel就存在
所以viewmodel实例的复用就变成ViewModelStore的复用了
ViewModelStore是在Activity中获取的,所以进入Activity#getViewModelStore()
可以看到NonConfigurationInstances中拿到ViewModelStore的
NonConfigurationInstances是用来因为配置变更时保存数据用的,它也保存了我们的ViewModelStore,那么是在哪里做了保存呢
你可以搜索一个NonConfigurationInstance哪里new出来的,
毕竟要保存就必须拿到NonConfigurationInstance.viewModelStore = xxx 去保存,所以我找到
onRetainNonConfigurationInstance方法中存了
而最终这个方法ActivityThread中调用到,涉及到activity销毁重建的流程,具体的流程你可以自己研究一下~
SavedState能力,viewmodel不是同一个实例都可以做到数据复用,怎么做到的?
几个重要类的类图
数据存储流程
数据恢复流程
数据复用流程
其实SavedState很简单,上面三张图就已经说全了,而且暂时也不知道怎么做解释,感觉代码截图出来都没什么好写的,如果日后有研究再写
为什么要使用viewmodel?意义在哪,为什么MVP也可以,为什么就要设计出vm层呢
-
因为传统的MVP中,P层还是会有view层的应用,而且P层不知道V层是否被销毁了。涉及到了一个异步回调问题,但是MVVM模式中,V层会依赖VM层,而VM层的生命周期是与V层一致的,就算数据来了,VM层也能通过感知宿主的生命周期去派发数据,不会造成内存泄漏。而且也没有V层的引用。
-
能做到Fragment之间的数据共享,比如主页中的Activity通常都有4个Tab,tab都是Fragment,如果Fragment之间要交付,免不了写一些回调,或者持有另一个Fragment的引用,耦合度很高。此时就可以让这4个Fragment用同一个ViewModel去操作了
-
其他的我想不到了,你晓得的话,评论区告诉我吧