简介
ViewModel是Jetpack中最重要的组件之一。传统开发模式下,Activity的任务实在太重了,既要负责逻辑处理,又要控制UI展示,甚至要处理网络回调。这是不符合软件设计模式的要求的,随着项目的不断扩大,这个项目会变得越来越难以维护。因为它在架构上是失败的。
ViewModel的一个重要作用就是分担Activity的一部分工作。即用于专门储存和管理用户界面相关的数据。这样Activity只需要承担UI控制器的职能。
另外,ViewModel还有一个关键的特性,ViewModel的生命周期和Activity不同,它可以保证在手机屏幕发生旋转时不会被重建,只有当Activity退出时才会跟着Activity一起销毁。因此将于界面相关的变量存放在ViewModel当中,这样即使旋转屏幕,界面上的数据也不会丢失。
不传入参数的使用
1. 添加依赖
在build.gradle(module:app)的dependencies块内,添加
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
2. 新建ViewModel的拓展类
class GameViewModel : ViewModel() {
...
}
3. 在片段(UI控制器)中添加ViewModel的引用
private lateinit var viewModel: GameViewModel
4. 初始化ViewModel
在配置更改(例如屏幕旋转)期间,将重新创建UI控制器(例如片段)。但是,ViewModel实例仍然存在。如果ViewModel使用ViewModel该类创建实例,则每次重新创建片段时都会创建一个新对象。所以使用ViewModelProvider来创建ViewModel实例。它会保证单例。
viewModel = ViewModelProvider(this).get(GameViewModel::class.java)
5. 在UI控制器中使用
经过以上设置,即可在UI控制器中调用ViewModel的方法来操纵数据,需要数据的地方直接访问ViewModel即可。
传入参数的使用
1. 1. 添加依赖
在build.gradle(module:app)的dependencies块内,添加
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
2. 新建ViewModel的拓展类
注意其有构造函数有参数
class ScoreViewModel(finalScore: Int) : ViewModel() {
var score = finalScore
...
}
3. 新建一个实现ViewModelProvider.Factory接口的类。
它是工厂类,给它构造函数添加一个参数(与前一步对应)
class ScoreViewModelFactory(private val finalScore: Int) : ViewModelProvider.Factory {
}
4. 添加上一步的具体实现
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(ScoreViewModel::class.java)) {
return ScoreViewModel(finalScore) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
5. 在UI控制器中添加ViewModel相关变量
private lateinit var viewModel: ScoreViewModel
private lateinit var viewModelFactory: ScoreViewModelFactory
6. 初始化viewModel工厂变量
其中的ScoreFragmentArgs 是自动生成的类。如果当前UI控制器有参数,就会生成这样一个Args类
viewModelFactory = ScoreViewModelFactory(ScoreFragmentArgs.fromBundle(arguments!!).score)
7. 使用工厂类构建viewModel变量
viewModel = ViewModelProvider(this, viewModelFactory).get(ScoreViewModel::class.java)
8. 在UI控制器中使用
经过以上设置,即可在UI控制器中调用ViewModel的方法来操纵数据,需要数据的地方直接访问ViewModel即可。