ViewModel 架构组件
ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。它允许数据在配置更改(如屏幕旋转)后继续留存。
为什么使用 ViewModel?
- 配置更改存活: 当 Activity 重建时,普通的成员变量会被销毁,而 ViewModel 实例会被保留。
- 职责分离: 将界面数据处理从 Activity/Fragment 中抽离,使 UI 控制器只负责渲染。
- 资源共享: 可以在同一 Activity 的多个 Fragment 之间共享数据。
添加依赖
kotlin
dependencies {
val lifecycle_version = "2.8.0"
// ViewModel 核心库
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")
// 如果在 Compose 中使用
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version")
}基本用法
第一步:定义 ViewModel
kotlin
class MyViewModel : ViewModel() {
private val _userCount = MutableLiveData<Int>(0)
val userCount: LiveData<Int> = _userCount
fun increment() {
_userCount.value = (_userCount.value ?: 0) + 1
}
}第二步:在 Activity 中获取
注意
切勿通过构造函数直接实例化 ViewModel!必须使用 ViewModelProvider。
kotlin
class MyActivity : AppCompatActivity() {
// 推荐使用 KTX 扩展属性
private val viewModel: MyViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.userCount.observe(this) { count ->
// 更新 UI
binding.textView.text = count.toString()
}
}
}ViewModel 的生命周期
ViewModel 的生命周期长于 Activity。它会一直存在,直到对应的生命周期作用域彻底销毁(如 Activity finish)。

进阶用法
在 Fragment 间共享数据
使用 activityViewModels() 获取作用域为 Activity 的 ViewModel。
kotlin
class SharedViewModel : ViewModel() { ... }
class ListFragment : Fragment() {
private val model: SharedViewModel by activityViewModels()
}
class DetailFragment : Fragment() {
private val model: SharedViewModel by activityViewModels()
}配合协程 (viewModelScope)
ViewModel 内置了 viewModelScope,在 ViewModel 清除时会自动取消其中的协程,防止内存泄漏。
kotlin
class UserViewModel(private val repository: UserRepository) : ViewModel() {
fun loadUserData() {
viewModelScope.launch {
val user = repository.getUser()
// ...
}
}
}进程死亡存活 (SavedStateHandle)
当系统因内存不足杀死进程后重建 Activity 时,普通的 ViewModel 数据会丢失(尽管它能抗住屏幕旋转)。SavedStateHandle 允许 ViewModel 在进程重建后恢复数据。
kotlin
class SavedStateViewModel(
private val state: SavedStateHandle // 自动注入
) : ViewModel() {
companion object {
private const val KEY_USER_ID = "uid"
}
// 1. 作为 LiveData/StateFlow 暴露 (自动保存)
val userId: LiveData<String> = state.getLiveData(KEY_USER_ID)
// 2. 普通读写
fun setUserId(id: String) {
state[KEY_USER_ID] = id // 立即保存到 Bundle 中
}
}