首先希望这篇文章如果对大家有帮助的话,可以点一个善意的赞或者收藏,这对我创作来说非常重要!先感谢大家啦~
1.ViewModel是什么?
官方解释: ViewModel是Jetpack组件里面一个具备宿主生命感知能力的数据存储组件;
从官方的解释可以看出有两点:
- 数据存储组件
- 具备宿主感知能力
从第一点来看,我首先有第一个疑问,数据存储组件?这有什么特别的,我为何不新建一个类保存数据,非要放到ViewModel呢?然后第二点乍一眼看,我盲猜ViewModel只是集成了LifeCycle的能力,然后才拥有的宿主感知能力吧?
接下来我们简单的解释一下以上的疑问吧~!
首先ViewModel他的作用确实是用于保存页面(甚至是应用维度)的数据,其次就是ViewModel拥有数据还原的能力,我们都知道一旦配置发生变化(页面旋转、分辨率调整、系统字体变更),Activity就会进行重建,在重建后如果我们的数据是定义在Activity上,那这个时候数据就会丢失,但是如果我们是放在ViewModel上,页面重建后我们拿到的ViewModel实体依旧是重建前的实体,那就意味着原本我们保存在ViewModel里面的数据也会得以保存。
但是这个时候就会有人有疑问,这只是重建啊,那么如果发生了因内存不足或者电量不足下的Activity回收,那回显时ViewModel也会恢复保存数据吗?
答案是会的,但是依赖SavedState这个组件,我们使用ViewModel + SaveState之后我们就能应对到这种情况!
而且使用ViewModel还有一个好处,就是充当MVVM里面VM的角色,让Activity的代码更加清爽,只专注View层相关的事务即可!如果有小伙伴不了解MVVM的话,可以去搜索一下相关资料,在这里就不展开说了!
至于宿主感知能力,我们就在原理章节顺路解开!话不多说我们先看看ViewModel是怎么使用的!
2.ViewModel怎么用?
既然是数据存储组件,我们关注的有以下几点:
- 怎么声明ViewModel?
- 怎么在Activity或Fragment中获取ViewModel?
2.1 声明ViewModel
//继承ViewModel
class MyViewModel: ViewModel(){
//在ViewModel下声明自己的数据
val data=MutableLiveData<String>()
//声明处理数据逻辑等函数
fun loadData():MutableLiveData<String> {
if (data.value == null) {
data.setValue(fetchDataFormRemote())
}
return data
}
fun fetchDataFormRemote():String{
return "从服务器获取的数据";
}
}
2.2 获得声明的ViewModel对象
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//通过ViewModelProvider获得我们上面声明的MyViewModel对象
val myViewModel = ViewModelProvider(this).get(MyViewModel::class.java)
//调用加载数据方法,并打印
print(myViewModel.loadData())
}
}
以上就是ViewModel + Activity最常用的使用方式了,可以说是很简单了~
2.3 其他使用场景
2.3.1 跨页面数据共享
比如我们有时候想保存一些全局数据,这时候很多页面都要获取该数据,那么除了声明静态数据之外,我们也可以通过以下方式保存全局数据:
//Application继承ViewModelStoreOwner接口,实现ViewModelStore能力
class MyApp : Application(), ViewModelStoreOwner {
private val viewModelStore: ViewModelStore by lazy {
ViewModelStore()
}
override fun getViewModelStore(): ViewModelStore {
return viewModelStore
}
}
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//与页面不同的是,我们通过application获取MyViewModel,此时ViewModel是保存在Application中
val myViewModel = ViewModelProvider(application).get(MyViewModel::class.java)
myViewModel.loadData()
print(myViewModel.data.value)
}
}
2.3.2 配合SavedState使用
//在构造函数中声明SavedStateHandle
class MyViewModel(val savedStateHandle: SavedStateHandle) : ViewModel() {
private val DATA_SAVE_KEY = "save_key";
val data = MutableLiveData<String>()
fun loadData(): MutableLiveData<String> {
if (data.value == null) {
//1.首先先从内存中尝试还原数据
val