ViewModel 简介

什么是 ViewModel?

说白了,ViewModel 就是帮你管数据的。屏幕一转、App 被回收,数据不会丢。

我刚学 Android 的时候,总把数据放在 Activity 或 Fragment 里。结果呢?一旋转屏幕,Activity 重建,输入框的内容全没了。用户骂我,老板也骂我。后来才知道,Google 早就给了解决方案——ViewModel。

ViewModel 是 Android Jetpack 的一部分。它专门用来存储和管理 UI 相关的数据。它的设计思想很简单:数据与界面解耦。Activity 可以死,但 ViewModel 活着,数据也就活着。

核心特性:
  • 自动保留数据,屏幕旋转不丢
  • 生命周期意识,自动清理
  • 跨 Fragment 共享数据

为什么需要 ViewModel?

这个问题我问过自己很多遍。你看啊,一个 App 里最怕的就是「状态混乱」。Activity 重建、Fragment 切换、网络请求回调还没回来……这些场景下,数据很容易丢失或重复加载。

用过 onSaveInstanceState 吗?那玩意儿只适合存少量序列化数据。图片、列表、复杂对象,根本塞不进去。ViewModel 就不一样,它直接存在内存里,只要你进程没被杀,数据就在。

我个人习惯把 ViewModel 当作「数据管家」。UI 只负责展示和通知,ViewModel 负责处理逻辑和缓存。这样写出来的代码,测试也好测,维护也轻松。

我的经验: 在大型项目中,ViewModel + Repository 模式几乎是标配。我曾经在一个电商 App 里,把商品详情、购物车、用户登录状态全部交给 ViewModel 管理。后来换 UI 框架(从 View 换成 Compose),只改了 UI 层,业务逻辑几乎没动。这就是解耦的好处。

ViewModel 的生命周期

ViewModel 的生命周期和 Activity/Fragment 不同。它的范围是从 Activity/Fragment 创建开始,到它真正被销毁为止。

看图就明白了:

ViewModel 生命周期与边界 Activity 生命周期 onCreate() onStart() / onResume() onPause() / onStop() onDestroy() ViewModel 生命周期 ViewModel 创建 数据处理 / 存活期 (旋转仍存活) ViewModel 销毁 注意:ViewModel 在 onDestroy 没有调用 finish() 或配置销毁时,不会立即销毁

图的左边是 Activity 的常规生命周期,右边是对应的 ViewModel 状态。关键点:Activity 旋转时 ViewModel 不会销毁。只有 Activity 真正 finish(比如用户按返回键),ViewModel 才会执行 onCleared()。

生命周期的陷阱

我曾经在项目里遇到一个问题:在 ViewModel 中持有 Activity 的 Context。结果旋转屏幕时,旧 Activity 无法被回收,导致内存泄漏。排查了好久才发现是 ViewModel 里传了 Activity 实例。正确的做法是用 Application 的 Context,或者直接使用 AndroidViewModel。

避坑指南: 切勿在 ViewModel 中持有 Activity、Fragment、View 等生命周期短的引用。如果需要 Context,请使用 AndroidViewModel(application: Application)。

ViewModel 的使用方式

用起来很简单,几句话就搞定:

// 创建一个 ViewModel
class MyViewModel : ViewModel() {
    val userData = MutableLiveData<User>()

    fun loadUser(userId: String) {
        // 加载数据的逻辑
    }
}

// 在 Activity 或 Fragment 中使用
val viewModel: MyViewModel by viewModels()
viewModel.userData.observe(this) { user ->
    // 更新 UI
}
方法 说明
viewModels() 在 Activity 中获取当前 Activity 范围的 ViewModel
activityViewModels() 在 Fragment 中获取共享的 Activity 范围 ViewModel
ViewModelProvider 自定义工厂模式创建 ViewModel(适用于带参数的情况)

我个人更推荐 by viewModels() 委托写法,省去样板代码。如果你需要传入 Application 或自定义参数,可以用 ViewModelProvider.Factory。

小技巧: 在 Fragment 间共享数据时,可以用 activityViewModels()。这样两个 Fragment 都能访问同一个 ViewModel,实现通信。我曾经用它做购物车页面,体验很好。

小结

ViewModel 不是个复杂的东西。它的核心就是「延长数据的生存期」。你只管写业务逻辑,ViewModel 帮你扛住配置变更和进程重建。

记住三个点:

  • 不要直接持有 Activity 引用
  • 用 LiveData 或 StateFlow 暴露数据
  • 生命周期绑定,自动清理

嗯,这就是 ViewModel 的基本面貌。后面会和 DataStore 配合,你会看到它真正的威力。