Android 进程重建与页面状态恢复
Android 进程重建与页面状态恢复
Android 页面可能因旋转、语言切换、后台内存压力等原因被重建。配置变化时进程通常仍在,ViewModel 可以继续持有状态;进程被系统回收后,内存对象全部消失,仅依赖 ViewModel 就无法恢复。可靠的状态恢复需要先区分哪些信息应自动保存,哪些应从持久化数据重新构建。
一、区分三类状态
页面中的数据可以分为:
- 导航参数:业务对象标识、入口来源等,决定页面是谁。
- 可恢复界面状态:选中的标签、输入草稿、滚动锚点等。
- 可重新加载数据:列表、详情、账户信息等,由仓库提供权威值。
大对象和完整接口响应不适合塞入保存状态。进程恢复时只保留重建所需的最小信息,再通过仓库加载内容。
二、ViewModel 不是持久化容器
ViewModel 能跨配置变化保存内存状态,但进程死亡后会重新创建。它适合组织页面逻辑,不应被当成永久缓存。
data class DetailUiState(
val itemId: String,
val selectedTab: Int,
val content: DetailContent? = null,
val loading: Boolean = false
)
其中 itemId 和 selectedTab 足以帮助恢复页面,content 则可以重新查询。
三、使用 SavedStateHandle 保存最小状态
class DetailViewModel(
private val savedStateHandle: SavedStateHandle,
private val repository: DetailRepository
) : ViewModel() {
private val itemId: String = checkNotNull(savedStateHandle[KEY_ITEM_ID])
val selectedTab = savedStateHandle.getStateFlow(KEY_TAB, 0)
fun selectTab(index: Int) {
savedStateHandle[KEY_TAB] = index
}
companion object {
private const val KEY_ITEM_ID = "item_id"
private const val KEY_TAB = "selected_tab"
}
}
业务必填参数直接按导航契约检查即可,不需要在缺失时猜测一个默认标识。保存内容应为体积小、可序列化且语义稳定的数据。
四、表单草稿需要明确策略
短表单可以保存少量输入值,长表单或包含附件的草稿更适合进入数据库。是否自动保存应考虑敏感性和用户预期。
密码、验证码等短时敏感信息不应进入普通状态保存。金额、身份信息等字段即使需要草稿,也应遵循项目安全存储规则。
fun updateRemark(value: String) {
savedStateHandle[KEY_REMARK] = value
}
输入过程中是否每次保存,要根据字段大小和更新频率决定。大文本可以在失焦或明确保存时处理。
五、避免重复执行一次性动作
页面恢复后,跳转、弹窗和轻提示不应仅因为状态重新订阅而再次执行。需要区分持久状态与一次性事件:
- 页面当前内容属于状态,新观察者应立即获取。
- 已完成跳转属于事件,不应在进程恢复时自动重放。
如果业务流程必须在恢复后继续,例如实名认证步骤,应保存“当前流程阶段”,由状态机决定下一界面,而不是保存一个待执行的跳转事件。
六、列表滚动位置如何恢复
列表组件可以保存自身布局状态,但恢复必须等待适配器拥有对应数据。过早恢复会被后续提交列表覆盖。
更稳定的业务方案是保存首个可见项的稳定标识和偏移,在数据加载完成后定位。若列表变化频繁,仅保存绝对位置可能指向不同内容。
七、处理数据过期
恢复出来的筛选条件和业务标识仍然有效,不代表旧数据仍然可信。仓库应根据业务缓存策略决定:
- 立即展示本地快照并刷新。
- 等待最新结果后展示。
- 对关键数据强制重新校验。
不要把保存状态中的时间戳当成通用可信依据。有效期由具体数据类型决定。
八、版本变化与键名稳定
应用升级后,进程恢复数据可能来自旧版本。保存字段应尽量简单,键名集中定义。字段语义变化时,需要兼容真实可能存在的旧值,而不是为所有想象情况增加分支。
自定义可序列化对象变化风险较高,优先保存标识、枚举值和基础类型。
九、测试进程重建路径
仅旋转屏幕不能完整覆盖进程回收。测试时应验证:
- 配置变化后不会重复请求或丢失选择。
- 进程重建后必填导航参数仍然存在。
- 数据重新加载前页面显示稳定加载状态。
- 一次性事件不会重复执行。
- 表单草稿按安全规则恢复。
- 列表数据准备完成后滚动位置正确。
总结
状态恢复的核心是保存重建线索,而不是保存整个页面。导航参数确定业务对象,SavedStateHandle 保存少量可恢复状态,仓库重新提供权威数据。区分配置变化和进程死亡,再处理一次性事件与数据过期,页面才能在系统重建后保持一致。
- 点赞
- 收藏
- 关注作者
评论(0)