ViewModel 生命周期管理详解ViewModel 是 Android Architecture ComponentsAAC的核心组件之一它的核心设计目标就是在配置变更如屏幕旋转时保持数据存活同时避免内存泄漏。下面从机制、类、知识点三个维度详细拆解。一、核心机制ViewModel 如何跨越配置变更1. 问题的本质当 Activity 因屏幕旋转被销毁并重建时系统会执行plainonDestroy() → 重建新实例 → onCreate()普通成员变量会随旧 Activity 一起销毁。ViewModel 的设计就是让数据与 Activity 实例解耦绑定到更稳定的作用域上。2. 关键洞察ViewModel 绑定的是逻辑上的 Activity而非实例系统为每个 Activity/Fragment 维护一个ViewModelStore这是一个键值对容器HashMapString, ViewModel。ViewModelStore 的生命周期与 Activity 的逻辑生命周期绑定而非具体的 Activity 实例。plain配置变更前 Activity实例A → 持有 ViewModelStore → 持有 ViewModel 配置变更后 Activity实例A 被销毁 ↓ ViewModelStore 被系统保留通过 NonConfigurationInstances 机制 ↓ Activity实例B 创建 → 复用同一个 ViewModelStore → 拿到同一个 ViewModel3. 真正的销毁时机ViewModel 只在以下情况被清除Activity 真正 finish()用户主动关闭、系统回收Fragment 被从 BackStack 移除且不再使用调用viewModelStore.clear()此时会触发ViewModel.onCleared()供开发者释放资源。二、涉及的核心类详解1.androidx.lifecycle.ViewModelkotlinabstract class ViewModel { // 标记是否已清除 private var mCleared false // 子类重写用于清理资源 protected open fun onCleared() {} // 内部方法由系统调用 internal fun clear() { mCleared true onCleared() } }所有自定义 ViewModel 的基类注意它本身不感知 Lifecycle只是一个数据容器 清理回调2.androidx.lifecycle.ViewModelStorekotlinclass ViewModelStore { private val mMap HashMapString, ViewModel() fun put(key: String, viewModel: ViewModel) { ... } operator fun get(key: String): ViewModel? { ... } fun clear() { // 遍历所有 ViewModel调用 clear() for (vm in mMap.values) { vm.clear() } mMap.clear() } }本质ViewModel 的缓存池以类名为 key或自定义 key存储 ViewModel 实例clear()时遍历所有 ViewModel 触发清理3.androidx.lifecycle.ViewModelStoreOwnerkotlininterface ViewModelStoreOwner { val viewModelStore: ViewModelStore }标识谁拥有 ViewModelStore实现者ComponentActivity、Fragment、NavBackStackEntry这意味着Activity、Fragment、导航图的返回栈都可以作为 ViewModel 的作用域4.androidx.lifecycle.ViewModelProvider这是创建 ViewModel 的工厂 缓存管理器kotlinclass ViewModelProvider( private val store: ViewModelStore, private val factory: Factory ) { fun T : ViewModel get(modelClass: ClassT): T { // 1. 先从 store 中查找 val existing store[canonicalName] if (existing ! null modelClass.isInstance(existing)) { return existing as T // 复用 } // 2. 没有则通过 Factory 创建 val newViewModel factory.create(modelClass) store.put(canonicalName, newViewModel) return newViewModel } }get()的幂等性同一个 key 多次调用返回同一个实例这就是 ViewModel 在配置变更后复用的核心逻辑5.ViewModelProvider.Factorykotlininterface Factory { fun T : ViewModel create(modelClass: ClassT): T }负责实际创建ViewModel 实例默认实现NewInstanceFactory用反射调用无参构造自定义场景ViewModel 需要带参数的构造函数时如 Repository、SavedStateHandle必须自定义 Factory6.SavedStateViewModelFactorykotlinclass SavedStateViewModelFactory( owner: SavedStateRegistryOwner, defaultArgs: Bundle? ) : ViewModelProvider.Factory支持在进程死亡后恢复数据的 Factory创建的 ViewModel 可以接收SavedStateHandle参数与onSaveInstanceState机制集成7.androidx.lifecycle.SavedStateHandlekotlinclass SavedStateHandle { fun T getLiveData(key: String): MutableLiveDataT operator fun T get(key: String): T? operator fun T set(key: String, value: T?) }在 ViewModel 中以键值对形式保存状态进程死亡后恢复时数据从 Bundle 中还原与LiveData集成getLiveData()返回的 LiveData 会自动持久化8.ComponentActivity/Fragment它们是 ViewModelStoreOwner 的实现者kotlinclass ComponentActivity : Activity(), ViewModelStoreOwner, LifecycleOwner, SavedStateRegistryOwner { // 在配置变更时保留 ViewModelStore override fun onRetainNonConfigurationInstance(): Any? { ... } }三、生命周期管理的底层实现1. Activity 如何保留 ViewModelStore在ComponentActivity中kotlinpublic ComponentActivity() { // 初始化 ViewModelStore mViewModelStore new ViewModelStore(); // 注册 NonConfigurationInstance 保留逻辑 getLifecycle().addObserver(new LifecycleEventObserver() { Override public void onStateChanged(...) { if (event ON_DESTROY) { if (!isChangingConfigurations()) { // 不是配置变更是真正销毁清除 ViewModel mViewModelStore.clear(); } } } }); } Override public final Object onRetainNonConfigurationInstance() { // 配置变更时把 ViewModelStore 放入 NonConfigurationInstances NonConfigurationInstances nci new NonConfigurationInstances(); nci.viewModelStore mViewModelStore; return nci; }onRetainNonConfigurationInstance()是系统提供的机制允许在配置变更时保留一个任意对象。ViewModel 就是利用这个机制把ViewModelStore保留下来。2. 新 Activity 如何恢复kotlinOverride public ViewModelStore getViewModelStore() { if (mViewModelStore null) { // 尝试从 NonConfigurationInstances 恢复 NonConfigurationInstances nc (NonConfigurationInstances) getLastNonConfigurationInstance(); if (nc ! null) { mViewModelStore nc.viewModelStore; } if (mViewModelStore null) { mViewModelStore new ViewModelStore(); } } return mViewModelStore; }3. Fragment 的 ViewModelStore 从哪来Fragment 有两种作用域表格作用域ViewModelStoreOwner生命周期Activity 作用域requireActivity()与 Activity 同生同死Fragment 自身作用域thisFragment 自身Fragment 销毁时清除kotlin// Activity 作用域 val viewModel: MyViewModel by activityViewModels() // Fragment 自身作用域 val viewModel: MyViewModel by viewModels()Fragment 自身的ViewModelStore由FragmentManager管理在 Fragment 真正销毁时清除。四、相关知识点体系1. Android Architecture Components (AAC)ViewModel 是 Google 官方架构组件之一同家族还有Lifecycle生命周期感知的基础LiveData可观察的数据持有者自动绑定生命周期Room数据库 ORMWorkManager后台任务Navigation导航组件Paging分页加载2. Lifecycle 组件kotlininterface LifecycleOwner { val lifecycle: Lifecycle } class Lifecycle { fun addObserver(observer: LifecycleObserver) }ViewModel 虽然不直接实现LifecycleObserver但它通过ViewModelStore与LifecycleOwnerActivity/Fragment绑定。3. 配置变更Configuration Changes包括但不限于屏幕旋转orientation键盘可用性变化keyboardHidden语言切换locale深色模式切换uiMode屏幕尺寸变化screenSize注意从 Android 7.0 开始多窗口模式下尺寸变化也会触发配置变更。4. 进程死亡与恢复Process Death Restoration系统内存不足时可能杀死后台进程。用户返回时重建plain进程被杀死 → Activity 重建 → onCreate(savedInstanceState)ViewModelStore 在进程死亡时不会保留需要持久化的数据应使用SavedStateHandle轻量级状态Room/DataStore/SharedPreferences大量数据5. 内存泄漏防范ViewModel 设计时就考虑了防泄漏不持有 Activity/Fragment 引用ViewModel 不应直接持有 View 或 LifecycleOwner 引用使用 LiveData/Flow通过观察者模式间接通信onCleared() 清理取消协程、释放监听器反模式示例kotlinclass BadViewModel : ViewModel() { private val activity: Activity? null // ❌ 内存泄漏 }6. Kotlin 协程与 ViewModelkotlinclass MyViewModel : ViewModel() { private val viewModelScope CoroutineScope(SupervisorJob() Dispatchers.Main) init { // viewModelScope 会在 onCleared() 时自动取消 } }viewModelScope是ViewModel的扩展属性内部使用CloseableCoroutineScope在clear()时自动取消所有协程。五、完整流程图plain用户旋转屏幕 │ ▼ Activity.onDestroy() ──► isChangingConfigurations()? ──► Yes │ │ │ ▼ │ ViewModelStore 被保留 │ (onRetainNonConfigurationInstance) │ │ ▼ │ No真正销毁 │ │ │ ▼ ▼ ViewModelStore.clear() 新 Activity 创建 │ │ ▼ ▼ ViewModel.onCleared() getLastNonConfigurationInstance() 释放资源 │ ▼ 恢复旧的 ViewModelStore │ ▼ ViewModelProvider.get() 发现已有实例直接返回 │ ▼ UI 继续使用同一个 ViewModel 数据不丢失六、总结表格维度要点核心思想ViewModel 与 Activity 实例解耦绑定到 ViewModelStore保留机制onRetainNonConfigurationInstance()/NonConfigurationInstances销毁时机Activity 真正 finish、Fragment 移除、手动 clear关键类ViewModel、ViewModelStore、ViewModelProvider、Factory、SavedStateHandle防泄漏不持有 View/Context使用 LiveData/Flow 通信进程恢复SavedStateHandle onSaveInstanceState 机制ViewModel 的生命周期管理本质上是作用域管理—— 它定义了一个比 Activity/Fragment 实例更长的作用域让数据在合理的范围内存活。