Kotlin ViewModel

Kotlin ViewModel 全流程指南

ViewModel 的核心作用是以注重生命周期的方式存储和管理界面相关的数据。它最伟大的地方在于:当手机屏幕旋转(配置更改)导致 Activity 重建时,ViewModel 中的数据不会丢失。


大纲

  1. 添加依赖
  2. [创建 ViewModel 类](#创建 ViewModel 类)
  3. 在-activity-或-fragment-中初始化
  4. [ViewModel 的生命周期](#ViewModel 的生命周期)
  5. [核心准则 Best Practices](#核心准则 Best Practices)
  6. 总结

1. 添加依赖

build.gradle.kts (Module: app) 中添加 Lifecycle 库:

kotlin 复制代码
dependencies {
    val lifecycle_version = "2.8.0" // 请检查最新版本
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")
    implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")
    // 如果在 Activity/Fragment 中使用 'by viewModels()' 扩展
    implementation("androidx.activity:activity-ktx:1.9.0")
}

2. 创建 ViewModel 类

ViewModel 应该存放所有的 UI 数据逻辑。建议配合 StateFlow 或 LiveData 使用,以实现响应式编程。

kotlin 复制代码
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow

class MyViewModel : ViewModel() {

    // 使用 StateFlow 管理状态
    private val _counter = MutableStateFlow(0)
    val counter: StateFlow<Int> = _counter

    fun incrementCounter() {
        _counter.value += 1
    }
}

3. 在 Activity 或 Fragment 中初始化

⚠️ 千万不要直接通过 val vm = MyViewModel() 来实例化,否则它就失去了生命周期感知的特性。必须通过 ViewModelProvider 或 by viewModels() 委托。

3.1 在 Activity 中

kotlin 复制代码
class MainActivity : AppCompatActivity() {

    // 使用 ktx 扩展函数(推荐)
    private val viewModel: MyViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 观察数据变化(以 Flow 为例)
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.counter.collect { count ->
                    // 更新 UI,例如:textView.text = count.toString()
                }
            }
        }
    }
}

3.2 在 Fragment 中(共享 ViewModel)

如果你希望 Fragment 之间共享数据,可以使用 activityViewModels()

kotlin 复制代码
class MyFragment : Fragment() {

    // 与宿主 Activity 共享同一个 ViewModel 实例
    private val sharedViewModel: MyViewModel by activityViewModels()
}

4. ViewModel 的生命周期

理解 ViewModel 的生命周期至关重要。它的存活时间比具体的 Activity 实例更长。

阶段 说明
创建 当 Activity 第一次启动时
存活 当 Activity 因为旋转屏幕而销毁并重新创建时,ViewModel 依然存在
销毁 只有当 Activity 真正彻底结束(调用 finish())或进程被杀掉时,ViewModel 才会调用 onCleared() 并销毁

5. 核心准则 (Best Practices)

5.1 禁止持有 Context

⚠️ 绝对不要在 ViewModel 中引用 Activity、Fragment 或 View(会导致内存泄漏)。

如果需要 Context,请继承 AndroidViewModel(application)

kotlin 复制代码
class MyAndroidViewModel(application: Application) : AndroidViewModel(application) {

    private val prefs = application.getSharedPreferences("my_prefs", Context.MODE_PRIVATE)

    fun saveData(key: String, value: String) {
        prefs.edit().putString(key, value).apply()
    }
}

5.2 单向数据流

复制代码
UI 观察 ViewModel 的状态  →  UI 的操作调用 ViewModel 的方法
                                    ↓
                           不要在 UI 中直接修改 ViewModel 的变量

5.3 轻量化

  • ViewModel 只负责 逻辑和数据
  • ViewModel 不负责 处理复杂的 UI 动画或具体的框架调用

总结

你是正在做传统的 XML 布局开发,还是已经在使用 Jetpack Compose 了?(Compose 中 ViewModel 的注入方式略有不同)。

关键点 说明
依赖添加 lifecycle-viewmodel-ktx + activity-ktx
实例化方式 by viewModels()ViewModelProvider,禁止 new MyViewModel()
数据管理 配合 StateFlow / LiveData 实现响应式
生命周期 跨配置变化存活,真正 finish 时销毁
最佳实践 不持有 Context,单向数据流,轻量化
相关推荐
vistaup2 小时前
kotlin 二维码实现高斯模糊
android·kotlin
愈努力俞幸运3 小时前
function calling与mcp
android·数据库·redis
阿巴斯甜4 小时前
LeakCanary
android
阿巴斯甜4 小时前
compose
android
阿巴斯甜4 小时前
Glide
android
-SOLO-4 小时前
使用Perfetto debug trace查看超时slice
android
阿巴斯甜4 小时前
Retrofit
android
阿巴斯甜5 小时前
OkHttp
android
阿巴斯甜5 小时前
Flow
android