一句话总结
Android ViewModel:UI数据的生命周期管理与解耦
ViewModel 是「数据的保险箱」,它帮你的数据在手机屏幕旋转、界面重建时存活下来,避免重复加载和丢失。
一、核心原理:UI与数据的解耦
ViewModel 的核心设计思想是将 UI 的生命周期与其相关数据分离开来。
- 生命周期长于UI:
ViewModel的生命周期从其宿主(如Activity或Fragment)首次创建时开始,一直存活到宿主彻底销毁为止(例如用户退出应用)。 - 配置变化下的持久性:当发生配置变化(如屏幕旋转)时,
Activity会被销毁并重建,但ViewModel会被系统保留,并与新创建的Activity关联。这使得数据可以在不被销毁的情况下,无缝地传递给新 UI。 - 幕后英雄:
ViewModelStore:每个Activity和Fragment都持有一个ViewModelStore实例,它是一个用于存储ViewModel的键值对容器。当Activity重建时,系统会确保ViewModelStore的实例被保留,从而保证ViewModel对象的唯一性。
二、ViewModel 的两大职责
1. 管理UI相关数据
ViewModel 的首要职责是持有和管理 UI 所需的数据。这些数据可以来自网络、数据库或本地文件。
-
如何暴露数据:
ViewModel不应该直接将数据暴露给 UI。最佳实践是使用可观察的数据持有者,如LiveData或StateFlow。这使得 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,如果使用不当,也可能导致内存泄漏。
- 不要持有
Context:ViewModel不应该持有Activity、Fragment或View的引用。如果确实需要Context,请使用**AndroidViewModel**,它提供了对Application的引用,而Application的生命周期与整个应用一致,不会导致泄漏。 - 在
onCleared()中释放资源:当ViewModel被销毁时,系统会调用onCleared()方法。这是释放手动创建的资源(如ExecutorService、文件句柄等)的最佳时机。
四、总结
ViewModel 是 Android 开发中构建健壮、可维护 MVVM 架构的核心。它通过将数据与 UI 的生命周期解耦,并提供了处理异步、持久化和避免内存泄漏的机制,极大地简化了开发者的工作,并显著提升了应用在配置变化时的用户体验。