onSaveInstanceState 是什么?
onSaveInstanceState(outState: Bundle) 是 Activity / Fragment 生命周期中的一个回调,系统在组件可能被销毁但需要后续恢复时调用,让你把关键状态保存到一个 Bundle 中。
你可以理解为:系统在说”我可能要杀掉你了,赶紧把重要的东西存一下,等会儿我帮你恢复”。
什么时候会触发?
- 屏幕旋转 — Activity 会销毁重建(Configuration Change)
- 按 Home 键 — Activity 进后台,可能被系统回收
- 切换到其他 App — 同上
- 多窗口模式切换
- 系统内存不足 — 后台 Activity 被杀
⚠️ 用户主动按返回键退出时不会调用
onSaveInstanceState,因为这是用户明确的销毁意图。
工作流程
Activity 即将不可见
→ 系统调用 onSaveInstanceState(bundle)
→ 你把关键数据存入 bundle
→ Activity 被销毁
→ 用户返回时,系统重建 Activity
→ onCreate(savedInstanceState) / onRestoreInstanceState() 中恢复数据基本用法
// 保存状态
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putInt("score", currentScore)
outState.putString("name", userName)
}
// 恢复状态 — 方式一:在 onCreate 中
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
savedInstanceState?.let {
currentScore = it.getInt("score")
userName = it.getString("name")
}
}
// 恢复状态 — 方式二:在 onRestoreInstanceState 中
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
currentScore = savedInstanceState.getInt("score")
}调用时机(相对于生命周期)
- API 28+(Android P):在
onStop()之后调用 - API 28 之前:在
onStop()之前调用,但不保证在onPause()之前还是之后
onPause()
↓
onStop()
↓
onSaveInstanceState() ← API 28+ 的调用时机FragmentActivity 的默认行为
FragmentActivity(AppCompatActivity 的父类)在 onSaveInstanceState() 的默认实现中会:
- 保存所有 Fragment 的状态
- 把 Intent 的 extras 也序列化到 Bundle 中
⚠️ 第 2 点很关键——如果 Intent extras 中有大数据(如大型 HashMap),这里会再次序列化,可能触发 TransactionTooLargeException。
防御性写法:
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
// 清除 Intent extras,防止大数据被二次序列化
intent?.removeExtra(PARAMS)
}注意事项
- Bundle 也有大小限制 — 和 Intent 一样走 Binder,总共 ~1MB
- 只存轻量数据 — 适合存 ID、位置、用户输入等;大数据用 ViewModel、Room、文件等
- 和 ViewModel 的区别:
| 特性 | onSaveInstanceState | ViewModel |
|---|---|---|
| 配置更改(如旋转)后存活 | ✅ | ✅ |
| 进程被杀后恢复 | ✅ | ❌ |
| 适合数据量 | 小(Bundle ~1MB 限制) | 大(内存级别) |
| 最佳实践 | 两者配合使用 | 两者配合使用 |