持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情
ViewModel介绍
ViewModel
是Android
官方开发JetPack
推荐专门用于和页面交互的数据管理类。它可与页面Activity/Fragment
生命周期绑定确保数据与页面生命周期同步以此达到最佳使用效果。例如页面A需要销毁重建,重新创建页面B。他们属于同一类型但是两个不同实例对象。但内部维护的数据源属于同一个在页面A销毁其数据过渡到页面B就需要使用到ViewModel了。
ViewModel使用
继承ViewModel
创建页面自己TestViewModel
对象。
class TestViewModel : ViewModel(){
var textIntValue : MutableLiveData<Int> = MutableLiveData<Int>()
}
在Activity
创建一个ViewModel
对象。通过ViewModelProvider
可创建TestViewModel
类型对象可以为其value
赋值。同时ViewModel
可设置observe
监听来知悉ViewModel
的value
值是否发生了变化以此刷新UI
展示结果。observe
的this
是页面的生命周期保证监听回调返回是在安全生命周期内的避免空指针情况发生。
PS:ViewModel也可以不和页面生命周期绑定,同样的observe方法不入参LifecycleOwner即可。但切记需要自行管理监听回调在安全情况下使用回调结果。
var viewModel = ViewModelProvider(this).get(TestViewModel::class.java)
viewModel.textIntValue.value = 1
viewModel.textIntValue.observe(
this
) { t ->
run {
findViewById<TextView>(R.id.tv_value).text = "viewModel $t"
}
}
此外在Fragment
中同样可以获取到和Activity
一样的ViewModel
对象。只要ViewModelProvider
入参是Activity
上下文即可,若Fragment
入参上下文是this
那么创建的ViewModel
只是该Fragment
自身的,这和ViewModelProvider
内部实现逻辑有关所有的ViewModel
由HashMap
形式保证内部全局类中。
viewModel = ViewModelProvider(requireActivity()).get(TestViewModel::class.java)
viewModel?.textIntValue?.observe(
viewLifecycleOwner
) { t ->
run {
view.findViewById<TextView>(R.id.tv_value).text = "viewModel $t"
}
}
实现ViewModel
以及数据监听之后,当ViewModel
数据发生变化后,Activity/Fragment
两者皆可在同一个对象中监听到数值变化回调。这也大大减少了数据传递的开发量可以说是EventBus
的便携式升级版,比起提供方法传参也更加解耦。
var value = viewModel?.textIntValue?.value ?: 0
if (viewModel?.textIntValue?.value != null) {
value.plus(1).also {
viewModel!!.textIntValue!!.value = it
}
}
MutableLiveData和LiveData
MutableLiveData
和LiveData
最大区别是可变和不可变。MutableLiveData
继承了LiveData
抽象类,MutableLiveData
提供了postValue
和setValue
方法。MutableLiveData
就是为其新增了可对数据源操作的能力。同时postValue
和setValue
也存在不同作用。
setValue
只能在主线程中使用不可在子线程操作postValue
可以在任何线程操作,因为它自身线程任务。- 但监听回调都是在主线程中发生。
小结
ViewModel
在业务开发中是比较实用的,对于多个数据源能做到数据区分,同时又能对数据做隔离处理。页面可以只关心UI而不关心数据处理,UI页面开发会变得更加清爽,所有业务数据处理在ViewModel
中进行。在很大程度上也解决了数据在多个页面同步的问题,不在想以前为了两个页面数据同步而设置方法或是接口互相调用"low代码"了。