Skip to content

ViewModel 架构组件

源: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)。

ViewModel 生命周期

进阶用法

在 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 中
    }
}