Android ViewModel:UI数据的生命周期管理与解耦

1,050 阅读3分钟

一句话总结

Android ViewModel:UI数据的生命周期管理与解耦

ViewModel 是「数据的保险箱」,它帮你的数据在手机屏幕旋转、界面重建时存活下来,避免重复加载和丢失。


一、核心原理:UI与数据的解耦

ViewModel 的核心设计思想是将 UI 的生命周期与其相关数据分离开来

  • 生命周期长于UIViewModel 的生命周期从其宿主(如 ActivityFragment)首次创建时开始,一直存活到宿主彻底销毁为止(例如用户退出应用)。
  • 配置变化下的持久性:当发生配置变化(如屏幕旋转)时,Activity 会被销毁并重建,但 ViewModel 会被系统保留,并与新创建的 Activity 关联。这使得数据可以在不被销毁的情况下,无缝地传递给新 UI。
  • 幕后英雄:ViewModelStore:每个 ActivityFragment 都持有一个 ViewModelStore 实例,它是一个用于存储 ViewModel 的键值对容器。当 Activity 重建时,系统会确保 ViewModelStore 的实例被保留,从而保证 ViewModel 对象的唯一性。

二、ViewModel 的两大职责

1. 管理UI相关数据

ViewModel 的首要职责是持有和管理 UI 所需的数据。这些数据可以来自网络、数据库或本地文件。

  • 如何暴露数据ViewModel 不应该直接将数据暴露给 UI。最佳实践是使用可观察的数据持有者,如 LiveDataStateFlow。这使得 UI 能够订阅数据,并在数据更新时自动刷新,从而实现了数据驱动的 UI。

  • 示例

    class UserProfileViewModel : ViewModel() {
        private val _user = MutableLiveData<User>()
        val user: LiveData<User> = _user
    
        fun fetchUser(userId: String) {
            // ... 异步从 Repository 获取数据
            _user.value = fetchedUser // 更新 LiveData
        }
    }
    

2. 处理异步与持久化

  • 异步操作ViewModel 是处理异步操作(如网络请求、数据库查询)的最佳场所。通过使用 viewModelScope,可以轻松地启动协程,并且当 ViewModel 被销毁时,这些协程也会被自动取消,从而避免了内存泄漏。
  • 进程重建下的数据恢复:为了应对进程被杀死的情况,ViewModel 可以通过 SavedStateHandle 来保存和恢复少量 UI 状态。SavedStateHandle 就像一个键值对的 Bundle,它与 ViewModel 的生命周期绑定,并在进程被重建后自动恢复数据。

三、避免内存泄漏的最佳实践

ViewModel 的生命周期长于 Activity,如果使用不当,也可能导致内存泄漏。

  • 不要持有 ContextViewModel 不应该持有 ActivityFragmentView 的引用。如果确实需要 Context,请使用**AndroidViewModel**,它提供了对 Application 的引用,而 Application 的生命周期与整个应用一致,不会导致泄漏。
  • onCleared() 中释放资源:当 ViewModel 被销毁时,系统会调用 onCleared() 方法。这是释放手动创建的资源(如 ExecutorService、文件句柄等)的最佳时机。

四、总结

ViewModel 是 Android 开发中构建健壮、可维护 MVVM 架构的核心。它通过将数据与 UI 的生命周期解耦,并提供了处理异步、持久化和避免内存泄漏的机制,极大地简化了开发者的工作,并显著提升了应用在配置变化时的用户体验。