一 概述
ViewModel 在Activity或者Fragment生命周期内只有一个的存储数据。ViewModel 里面的数据不会因为屏幕的旋转或者其他配置(比如切换到多窗口模式)而丢失。但是在正常的finish()或者按返回键的时候,在Activity或者Fragment走到onDestroy的时候回清除ViewModel里面的数据,避免内存泄漏。虽然屏幕旋转Activity也会走onDestroy,但是会判断是否是因为屏幕旋转而导致的。所以ViewModel是一个很合格的存储数据的类
二 ViewModel生命周期
ViewModel 对象存在的时间比Activity的生命周期要长,禁止在ViewModel的持有Activity、Fragment、View等对象,这样会引起内存泄漏。如果需要在ViewModel中引用Context的话,google为我们提供了AndroidViewModel 类来供我们使用。
三 ViewModel的好处
- 不会因为屏幕旋转或者其他配置改变(比如切换到多窗口模式)而销毁,避免数据重新创建,比如网络数据重新加载的情况
- 当Activity或者Fragment的正常销毁的时候,自动清除数据,也就是绑定了Activity或者Fragment的生命周期,避免了内存泄漏,
- 多个Fragment之间或者Activity和Fragment之间更好地传递数据,进行交互
- 减少Activityu或者Fragment的压力,Activityu或者Fragment的只是显示数据的界面,帮助Activity和Fragment处理一些数据逻辑
3.1 由于官网的例子有点老,所以写一个共享的例子
Activity 中的两个或更多 Fragment 需要相互通信是一种很常见的情况。Activity和Fragment的之间互相调用,下面是一个Activity和两个Fragment之间的互相调用
具体的demo地址github
3.1.1 构建一个Avtivity
class ViewModelDemoActivity : AppCompatActivity() {
// 创建以Activity为维度的ViewModel
private val viewModel: DemoViewModel by lazy {
ViewModelProvider(this).get(DemoViewModel::class.java) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var binding = DataBindingUtil.setContentView<ActivityViewmodelDemoBinding>(
this,
R.layout.activity_viewmodel_demo
)
viewModel.dataLive.observe(this, object : Observer<String> {
override fun onChanged(s: String?) {
// 当横竖屏变换时,会重新走这里,毕竟是View也都重新绘制了,只不过user里面立马有值
tv_name.text = s
}
})
tv_name.setOnClickListener{
// activity 里面的点击去改变值
viewModel.dataLive.value= "Activity触发的改变"
}
viewModel.getName()
}
companion object {
fun startMe(activity: Activity) {
activity.startActivity(Intent(activity, ViewModelDemoActivity::class.java))
}
}
}
3.1.2 ViewModel的代码
class DemoViewModel : ViewModel() {
val dataLive: MutableLiveData<String> =
MutableLiveData<String>()
fun getName(){
viewModelScope.launch {
delay(1000)
dataLive.value = "王者荣耀"
}
}
}
3.1.3 布局文件
两个Fragment是通过静态方式添加到Activity的
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android