ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Activity 的状态改变、状态保存

Activity 的状态改变、状态保存 Android 页面状态丢失主要来自两类情况配置变更导致页面重建例如屏幕旋转深色模式切换语言切换屏幕尺寸变化旧 Activity 被销毁 ↓ 创建新的 Activity 实例但应用进程一般还活着。2. 应用进程被系统回收例如应用进入后台后系统因内存不足杀死应用进程Activity、ViewModel、Application 全部消失 ↓ 用户重新返回应用 ↓ 系统重新创建进程和 Activity一、onSaveInstanceState 与 ViewModel 的本质区别它们最大的区别在于应对“配置变更”和“系统发起的进程死亡”时的处理方式不同。对比维度onSaveInstanceStateViewModel核心目的保存少量、临时的 UI 状态例如滚动位置、输入框文字、选中的 ID持有并管理界面相关的数据例如网络请求结果、用户列表和页面状态生命周期范围保存的状态由系统 Saved State 机制管理不依赖旧 Activity 实例继续存活跟随 Activity、Fragment 等 ViewModelStoreOwner 的作用域配置变更时✅ 旧 Activity 销毁保存的数据通过 Bundle 传递给新 Activity✅ ViewModel 实例保留新 Activity 获取同一个实例系统发起进程死亡时✅ 可恢复之前保存的少量状态❌ ViewModel 及内存数据全部丢失数据存储方式数据转为 Bundle 支持类型交由系统持久化管理存储在当前应用进程堆内存中代码职责通常由 Activity / Fragment / View 执行保存与恢复逻辑页面数据、业务逻辑可从 Activity/Fragment 剥离解耦数据量限制必须轻量受 Binder 缓冲区限制约1MB进程共享禁止存放大对象无 Bundle 序列化限制但受应用最大堆内存约束二、这就引出了“尴尬的灰色地带”想象一个场景用户在购物车页面ViewModel里存了十几个商品对象用户按下 Home 键切到后台。此时系统内存不足杀掉了应用进程。ViewModel被杀死商品数据丢失因为它在内存里。onSaveInstanceState虽然幸存但商品列表里的图片、大文本等数据量太大根本不适合序列化进 Bundle强行存会崩溃。所以单纯的ViewModel无法应对“进程死亡”而onSaveInstanceState又不适合存稍大一点、复杂的业务数据。这导致开发者往往需要两头写代码ViewModel存大对象onSaveInstanceState存小标记比如购物车ID重建时用 ID 去数据库或网络重新拉取。这种“两头对接”的方式非常繁琐且容易出错。三、SavedStateHandle破局的“桥梁”SavedStateHandle正是为了解决上述痛点而生的。它本质上是一个专属于ViewModel的“保险箱”充当了ViewModel和系统onSaveInstanceState机制之间的桥梁。它的核心作用是让 ViewModel 拥有“进程被强杀后自动恢复”的能力而无需在 Activity/Fragment 中写任何序列化或恢复代码。1. 它是如何工作的当系统准备销毁进程时SavedStateHandle会自动将其内部存储的 Key-Value 数据写入系统的Bundle即走的onSaveInstanceState通道。当进程重建时系统自动将这个 Bundle 恢复并重新注入到新的ViewModel实例中。关键点SavedStateHandle内部有一个SavedStateRegistry与系统挂钩这个过程对开发者完全透明。2. 它如何简化开发你不再需要在 Activity 中重写onSaveInstanceState()去保存某个 ID再在onCreate里取出来传给 ViewModel。所有状态保存和恢复的逻辑现在都统一写在 ViewModel 内部了。3. 典型用法示例假设有一个用户详情页只需要保存一个userIdclassUserViewModel(privatevalsavedStateHandle:SavedStateHandle):ViewModel(){// 方式一直接读写funsaveUserId(id:String){savedStateHandle[user_id]id}fungetUserId():String?{returnsavedStateHandle[user_id]}// 方式二使用委托最简洁推荐varuserId:StringbysavedStateHandle.string(user_id,default_id)// 方式三配合 LiveData 使用界面观察变化valuserName:MutableLiveDataStringsavedStateHandle.getLiveData(user_name,DefaultName)}当界面因内存不足被重建时这个userId会自动恢复ViewModel拿到它后直接发起网络请求获取新的用户详情界面无缝刷新。4. 使用它的核心约束轻量级它依然是走 Bundle 序列化的通道默认受 1MB 大小限制。存列表或图片依然不合适存 ID再重新拉取才是正解。不可持久化用户主动从最近任务划掉应用或应用被卸载数据永久丢失它只保进程死亡不保应用彻底关闭。四、一句话总结三者的关系onSaveInstanceState是系统的“序列化仓库”只存小东西且必须由 Activity 亲自管理。ViewModel是内存中的“大型数据仓库”配置变更时不怕但进程死亡就完蛋。SavedStateHandle是“ViewModel 随身携带的钥匙”让 ViewModel 可以随时把关键的小数据锁进系统的“序列化仓库”里让 ViewModel 同时具备了抵抗进程死亡的能力且代码高度内聚无需界面层参与。
返回列表