Android 进程重建与页面状态恢复

举报
shenlan9755 发表于 2026/09/18 09:32:13 2026/09/18
【摘要】 Android 进程重建与页面状态恢复Android 页面可能因旋转、语言切换、后台内存压力等原因被重建。配置变化时进程通常仍在,ViewModel 可以继续持有状态;进程被系统回收后,内存对象全部消失,仅依赖 ViewModel 就无法恢复。可靠的状态恢复需要先区分哪些信息应自动保存,哪些应从持久化数据重新构建。 一、区分三类状态页面中的数据可以分为:导航参数:业务对象标识、入口来源等,...

Android 进程重建与页面状态恢复

Android 页面可能因旋转、语言切换、后台内存压力等原因被重建。配置变化时进程通常仍在,ViewModel 可以继续持有状态;进程被系统回收后,内存对象全部消失,仅依赖 ViewModel 就无法恢复。可靠的状态恢复需要先区分哪些信息应自动保存,哪些应从持久化数据重新构建。

一、区分三类状态

页面中的数据可以分为:

  • 导航参数:业务对象标识、入口来源等,决定页面是谁。
  • 可恢复界面状态:选中的标签、输入草稿、滚动锚点等。
  • 可重新加载数据:列表、详情、账户信息等,由仓库提供权威值。

大对象和完整接口响应不适合塞入保存状态。进程恢复时只保留重建所需的最小信息,再通过仓库加载内容。

二、ViewModel 不是持久化容器

ViewModel 能跨配置变化保存内存状态,但进程死亡后会重新创建。它适合组织页面逻辑,不应被当成永久缓存。

data class DetailUiState(
    val itemId: String,
    val selectedTab: Int,
    val content: DetailContent? = null,
    val loading: Boolean = false
)

其中 itemIdselectedTab 足以帮助恢复页面,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 保存少量可恢复状态,仓库重新提供权威数据。区分配置变化和进程死亡,再处理一次性事件与数据过期,页面才能在系统重建后保持一致。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。