在 Android 开发中,ViewModel 的核心使命是以注重生命周期的方式存储和管理界面相关的数据。它解决了 Activity/Fragment 在配置更改(如屏幕旋转)时销毁重建导致的数据丢失问题。
以下是 ViewModel 的几种最常用的用法:
1. 核心用法:处理配置更改
这是 ViewModel 最基础的用途。传统的 Activity 在旋转屏幕时会重新调用 onCreate(),如果你把数据存在 Activity 成员变量里,数据会直接重置。
-
用法:将 UI 数据(列表、表单内容)放在 ViewModel 中。
-
原理 :ViewModel 的生命周期比 Activity 长,直到 Activity 彻底关闭(Finished)时,ViewModel 才会执行
onCleared()。
2. 结合 LiveData 或 StateFlow 实现响应式 UI
这是目前最主流的架构模式(MVVM)。ViewModel 不应该持有 View 的引用,而是通过"发布/订阅"模式通知 UI。
-
数据流向 :ViewModel 修改内部数据 \\rightarrow 暴露为
LiveData或StateFlow\\rightarrow Activity 观察(Observe)并更新 UI。 -
优点:UI 始终能反映最新数据,且避免了空指针异常(因为观察者感知生命周期)。
3. 片段间的数据共享 (Shared ViewModel)
在同一个 Activity 下的多个 Fragment 需要通信(比如:左侧列表点击,右侧详情显示)时,ViewModel 是最佳中转站。
-
用法 :在 Fragment 中初始化时,使用 Activity 范围的 ViewModel 实例。
-
代码示例:
// Fragment A 和 B 都绑定到相同的 Activity 作用域 val sharedViewModel: MyViewModel by activityViewModels() -
好处:Fragment 之间互不耦合,通过同一个 ViewModel 实例交换信息。
4. 封装业务逻辑与 Repository 通信
ViewModel 充当了 UI 控制器和数据层(Repository/Database)之间的桥梁。
-
用法:在 ViewModel 中调用 Repository 获取数据。
-
异步处理 :利用
viewModelScope开启协程进行耗时操作(如网络请求或数据库查询)。 -
自动清理 :当 ViewModel 销毁时,
viewModelScope会自动取消正在进行的协程,防止内存泄漏。
5. 处理 SavedStateHandle (异常恢复)
虽然 ViewModel 能处理配置更改,但无法应对系统内存不足导致的进程被杀。
-
用法 :在 ViewModel 构造函数中注入
SavedStateHandle。 -
功能:你可以像使用 Bundle 一样存取关键状态(如用户 ID),即使进程被重启,数据也能找回来。
总结:常用模式对比
| 场景 | 推荐用法 |
|---|---|
| 单页面数据存储 | private val _data = MutableLiveData<T>() |
| 多片段共享数据 | 使用 activityViewModels() 获取单例 |
| 执行网络请求 | 在 viewModelScope.launch { ... } 中执行 |
| 处理复杂逻辑 | 组合 Repository 模式,保持 ViewModel 简洁 |
| 防止进程杀掉 | 使用 SavedStateHandle 存取关键 Key |
你目前是在从传统的 MVC/MVP 模式转向 MVVM 吗?还是在考虑如何更好地结合 Jetpack Compose 使用 ViewModel?