在 Kotlin Android 开发中,当一个类继承了 ViewModel ,这就意味着这个类想要成为当前页面(Activity / Fragment / Compose 屏幕)的**"大脑"或"数据管家"**。
简单来说,它的核心目的是:把"界面显示"和"背后的业务逻辑与数据"彻底分离开来。
当开发者让一个类继承 ViewModel 时,他主要想利用 ViewModel 的以下几个"超能力":
1. 扛住"屏幕旋转"等毁灭性打击(生命周期感知)
这是 ViewModel 最著名的作用。
在 Android 中,当你旋转手机屏幕 、或者切换系统语言 时,系统会把当前的 Activity 直接销毁,然后重新创建一个新的 Activity。
-
如果不使用 ViewModel:你在页面上输入了一半的文字、或者刚从网络下载好的列表数据,会随着 Activity 的销毁瞬间清空。你必须重新请求网络,用户体验极差。
-
继承了 ViewModel 后 :ViewModel 的生命周期比普通 Activity 长。在屏幕旋转导致 Activity 销毁重建的过程中,ViewModel 会安然无恙地存活在内存中。当新的 Activity 创建好后,它可以直接从 ViewModel 里拿回刚才的数据,瞬间恢复页面。
2. 分离关注点(让代码不再像意大利面条一样缠绕)
现代 Android 开发极其强调"各司其职":
-
Activity / Compose 界面 :只负责"画图"和"监听用户点击"。它不应该知道数据是怎么从服务器下载的,也不应该处理复杂的计算。它就像个提线木偶。
-
ViewModel :就是那个幕后操纵者。它负责向上网请求数据、读写数据库、处理业务逻辑,然后把处理好的数据(UI State)准备好,供界面去使用。
3. 方便地管理响应式数据(StateFlow / LiveData)
继承了 ViewModel 的类,通常会在里面定义 StateFlow 或 LiveData。
这是一种**"观察者模式"。ViewModel 把数据放在这里,界面只要"订阅(Observe)"它。一旦 ViewModel 里的数据发生变化(比如网络请求成功,拿到了新数据),界面就会自动刷新**,你不需要手动去写 textView.text = "新数据"。
4. 自动管理耗时任务,防止内存泄漏 (viewModelScope)
在 Android 中发网络请求必须在后台线程(协程)进行。如果用户在网络请求还没完成时,就按了返回键退出了页面,这个请求如果不取消,就会导致内存泄漏 或程序崩溃。
继承 ViewModel 后,你会免费获得一个叫 viewModelScope 的东西。你在这里面启动的任何网络请求,只要 ViewModel 被销毁(用户真正退出了这个页面),所有没做完的任务都会被自动取消,极其安全。
💡 一个形象的比喻
-
Activity / 手机屏幕 就像是 电视机的显示屏。它只负责把画面亮起来给你看。
-
ViewModel 就像是 电视机顶盒(或游戏主机)。它负责接收信号、处理图像数据、保存你的游戏进度。
当你把电视机电源拔了再插上(屏幕旋转重建),只要机顶盒(ViewModel)还开着,画面就能瞬间恢复。
👨💻 代码长什么样?
code Kotlin
downloadcontent_copy
expand_less
// 继承了 ViewModel
class LoginViewModel : ViewModel() {
// 保存界面的状态(比如:正在加载中)
var isLoading = MutableStateFlow(false)
private set
// 处理用户点击登录的逻辑
fun login(username: String, psw: String) {
// 使用 viewModelScope 启动协程,页面退出会自动取消
viewModelScope.launch {
isLoading.value = true // 告诉界面:开始转圈圈
// 模拟网络请求...
delay(2000)
isLoading.value = false // 告诉界面:转圈圈结束
}
}
}