在 Android 10+ 中,如何处理后台 Activity 被系统回收后的状态恢复?
解读
国内 ROM 在内存紧张时比 AOSP 更激进,后台进程几分钟就可能被“杀缓存”。面试时,面试官想确认两点:
- 你是否真的遇到过“页面重启”导致的空指针 / Fragment 重叠 / 数据丢失;
- 你是否能把“系统回收 → 进程死亡 → 重新创建”整条链路讲清楚,并给出可落地的代码级方案,而不是背官方文档。
回答要围绕“保存-恢复”闭环,兼顾 Java/Kotlin 双语言,并点出 Android 10 之后 SavedStateHandle、自动恢复限制等新变化。
知识点
- 回收触发条件:Low Memory Killer、厂商后台管控、adb shell am kill、用户“划掉”任务。
- 重建流程:系统通过 ActivityThread 重新创建 Application → 反射构造 Activity → 调用 attach() → 分发 onCreate(savedInstanceState)。
- 状态载体:
- Activity/Fragment 的 onSaveInstanceState(Bundle) / SavedStateRegistry
- View 的 android:saveEnabled + onSaveInstanceState / onRestoreInstanceState
- Jetpack ViewModel 的 SavedStateHandle(Android 10 正式引入)
- 非 UI 数据:Room、DataStore、MMKV、文件、云端同步
- 大小限制:Binder 1 MB 事务缓冲区,单个 Bundle 超过 ~200 k 会触发 TransactionTooLargeException;图片、列表等不能直写 Bundle。
- 恢复时机:onCreate / onRestoreInstanceState;Fragment 在 onViewStateRestored;Compose 用 rememberSaveable。
- 国内特殊场景:
- 微信、QQ 保活白名单不可依赖;
- 小米/华为“锁屏清理内存”会把整个进程杀掉,重启后无回调,只能靠持久化;
- 部分 ROM 会屏蔽 START_ACTIVITIES_FROM_BACKGROUND,跳转前需加 FOREGROUND_SERVICE 权限或用户可见窗口。
- 调试命令:
adb shell am kill <package>
adb shell cmd activity stop-app <package>
开发者选项“不保留活动”模拟极端回收。
答案
“我在线上通过 Bugly 捕获过大量 IllegalStateException: Can not perform this action after onSaveInstanceState,根本原因是进程被杀后重建时 Fragment 事务提交时机不对。针对 Android 10+,我分四层做状态恢复:
- UI 轻量状态:
在 Activity 与 Fragment 中统一重写 onSaveInstanceState(outState: Bundle),只放用户当前阅读位置、选中 Tab 等基础字段;对 RecyclerView 的滚动位置使用 ParcelableUtil 封装,防止过大。 - 业务数据:
把列表数据、搜索关键字放到 ViewModel 的 SavedStateHandle,通过 handle.getLiveData() 自动恢复;超过 Binder 限制的数据走 Room 缓存,key 存数据库主键,Bundle 只写主键。 - 大图与缓存:
图片 URL 与 Glide 缓存 key 持久化到 DataStore,重建时按屏幕宽度重新采样,避免 TransactionTooLarge。 - 兜底策略:
在 Application.onCreate 里读取最后一次 Activity 记录(SP 存 simpleName + intent uri),若检测到非正常死亡且用户 30 分钟内返回,弹半屏‘继续浏览’浮层,点击后带 FLAG_ACTIVITY_CLEAR_TOP 重启原页面并拉取最新数据,保证体验闭环。
上线后同类崩溃从 0.8% 降到 0.02%,后台统计用户重进流失率下降 35%。”
拓展思考
- 如果业务是音视频播放,进度条状态放 SavedStateHandle 仍可能丢 3~5 秒,可结合 MediaSession + PlaybackState 持久化到 Room,并在 onPrepared 时 seekTo(lastPosition - 2s) 做补偿。
- 多模块组件化场景,各业务模块可自定义 SavedStateProvider 注册到 Activity 的 SavedStateRegistry,实现“谁产生状态谁负责恢复”,避免在基类 Activity 写一堆 if-else。
- Android 12 引入的“自动重置权限”会让后台被杀后首次启动缺失权限,需在恢复流程中先检查权限再渲染 UI,否则状态恢复成功但功能仍不可用。