02-Activity异常生命周期与状态恢复
Activity 异常生命周期与状态恢复
1. 什么是异常生命周期?
正常生命周期通常由用户操作触发:
打开页面
切换页面
按 Home
按返回键
异常生命周期通常由系统环境变化或资源回收触发:
横竖屏切换
语言切换
深色模式变化
屏幕尺寸变化
字体缩放变化
多窗口尺寸变化
内存不足导致进程被回收
这些情况可能导致 Activity 被销毁并重新创建。
2. 配置变化导致 Activity 重建
没有特殊配置时,横竖屏切换、语言切换、屏幕尺寸变化等都可能导致 Activity 重建。
常见流程可以理解为:
旧 Activity:
onPause()
onStop()
onDestroy()
新 Activity:
onCreate()
onStart()
onResume()
如果系统认为这个 Activity 之后可能被恢复,会触发状态保存:
onSaveInstanceState()
新实例创建时,可以通过:
onCreate(savedInstanceState)
onRestoreInstanceState(savedInstanceState)
恢复之前保存的临时状态。
3. onSaveInstanceState() 的作用
onSaveInstanceState() 用来保存 Activity 被系统临时销毁前的 UI 状态。
示例:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("username", username);
outState.putInt("pageIndex", pageIndex);
}
适合保存:
输入框临时内容
当前 Tab
列表滚动位置
页面临时筛选条件
当前页码
不适合保存:
大对象
图片 Bitmap
大量列表数据
数据库数据
长期业务状态
原因是 Bundle 需要跨进程传递,数据太大可能造成性能问题,甚至触发异常。
4. 版本差异:onSaveInstanceState() 和 onStop() 顺序
原 PDF 中提到:
onSaveInstanceState() 总是在 onStop() 之前
这个说法只适合早期 Android 行为,不能作为现在的固定结论。
更准确的版本差异如下:
| 版本 / target 情况 | 顺序说明 |
|---|---|
| API 28 之前 | onSaveInstanceState() 一般在 onStop() 之前;相对 onPause() 的顺序不应强依赖 |
| target API 28+ | onSaveInstanceState() 在 onStop() 之后调用 |
因此不要写依赖强顺序的代码。
更推荐的理解是:
onPause / onStop:处理页面离开前台、不可见相关逻辑
onSaveInstanceState:保存系统重建时需要恢复的临时 UI 状态
5. onSaveInstanceState() 不一定会调用
onSaveInstanceState() 不是普通生命周期方法,不是每次 onPause() 或 onStop() 都一定调用。
典型不会调用或不应依赖的场景:
用户按返回键主动退出 Activity
代码调用 finish()
系统直接杀死整个进程
因为用户主动退出通常表示“不需要恢复这个 Activity”。
6. onRestoreInstanceState() 的作用
onRestoreInstanceState() 用于恢复之前保存的数据。
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
String username = savedInstanceState.getString("username");
int pageIndex = savedInstanceState.getInt("pageIndex");
}
它一般在:
onStart() 之后
onResume() 之前
被调用。
7. 也可以在 onCreate() 中恢复数据
onCreate() 也有 savedInstanceState 参数:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
String username = savedInstanceState.getString("username");
}
}
两种方式对比:
| 方法 | 特点 |
|---|---|
onCreate() |
每次创建都会调用,所以需要判断 savedInstanceState != null |
onRestoreInstanceState() |
只有确实存在可恢复状态时才会调用 |
8. 系统会自动恢复部分 View 状态
Android 会自动保存和恢复部分 View 状态,比如:
EditText 输入内容
ScrollView / RecyclerView / ListView 的部分滚动状态
CheckBox 选中状态
前提通常是:
View 有稳定 id
View 实现了状态保存逻辑
Activity 走了状态保存和恢复流程
所以需要恢复状态的 View,应该设置稳定的 android:id。
9. View 状态保存的委托流程
可以理解为:
Activity
↓
Window
↓
DecorView
↓
ViewGroup
↓
子 View
Activity 不会亲自保存每个 View 的状态,而是层层委托。
这种委托思想在 Android 里很常见:
View 绘制流程
事件分发流程
View 状态保存流程
10. 内存不足导致 Activity 所在进程被回收
当系统内存不足时,可能杀死低优先级进程。
常见优先级大致是:
前台进程 > 可见进程 > 服务进程 > 后台 / 缓存进程
如果 Activity 已经 onStop(),所在进程更容易被回收。
这时不要指望:
onDestroy() 一定执行
应该把关键状态保存提前做掉。
11. 总结
配置变化重建:用 onSaveInstanceState / onRestoreInstanceState 保存临时 UI 状态
用户主动退出:不要期待 onSaveInstanceState 保存
进程被杀:不要期待 onDestroy 兜底
记忆口诀:
临时状态怕重建,Bundle 保存现场。
关键数据怕丢失,及时落库别等销毁。
参考来源
- 原始 PDF:《01、Activity知识总结.pdf》
- Android 官方文档:Activity 生命周期
https://developer.android.com/guide/components/activities/activity-lifecycle - Android 官方文档:Activity API Reference
https://developer.android.com/reference/android/app/Activity - Android 官方文档:处理配置变更
https://developer.android.com/guide/topics/resources/runtime-changes - Android 官方文档:
<activity>manifest 配置
https://developer.android.com/guide/topics/manifest/activity-element - Android 官方文档:Tasks and back stack
https://developer.android.com/guide/components/activities/tasks-and-back-stack - Android 官方文档:Services overview
https://developer.android.com/develop/background-work/services