一、这玩意儿到底是个啥?
savedInstanceState
就像你打游戏时的存档点。想象你正在玩《原神》,突然接电话退出游戏:
- 如果游戏有存档功能,回来还能接着玩
- 没存档?只能从最近的传送点重来
在Android里,当系统杀你Activity时(比如屏幕旋转/内存不足),这个Bundle就是用来存档的:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 这里判断是不是复活甲生效了
if (savedInstanceState != null) {
// 读取之前的存档
val score = savedInstanceState.getInt("current_score")
} else {
// 全新开局
}
}
二、什么时候会用到它?
2.1 必考场景(划重点):
- 屏幕旋转(开发者最熟悉的陌生人)
- 分屏模式切换
- 系统杀后台(特别是国产手机)
- 从最近任务列表移除应用
2.2 特别注意:
// 下面这些情况不会触发存档!
val intent = Intent(this, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
startActivity(intent) // 这种自杀重启不会保存状态
三、正确使用姿势(附翻车案例)
3.1 保存数据就像打包外卖:
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
// 一定要先调用父类方法!
outState.putString("user_input", editText.text.toString())
// 注意!这些类型不能存:
// ❌ Bitmap(太大)
// ❌ 自定义对象(除非实现Parcelable)
// ❌ 数据库连接(会泄露)
}
3.2 恢复数据像热剩饭:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// 正确判断顺序:
when {
savedInstanceState != null -> {
// 1. 优先使用存档数据
editText.setText(savedInstanceState.getString("user_input"))
}
arguments != null -> {
// 2. 其次用Intent传的参数
editText.setText(arguments?.getString("default_text"))
}
else -> {
// 3. 最后才是默认值
editText.setText("")
}
}
}
3.3 翻车现场实录:
// 错误示范1:忘记判断null
val data = savedInstanceState!!.getString("key") // 可能闪退
// 错误示范2:和ViewModel重复存储
// 应该用ViewModel保存复杂数据,Bundle只存简单状态
// 错误示范3:存了不该存的东西
outState.putSerializable("user", User()) // 除非User实现Serializable
四、高级技巧(面试装逼用)
4.1 自动保存View状态原理
每个View的onSaveInstanceState()
会被自动调用,前提是:
- 设置了id(没id的View系统不知道你是谁)
- 不要设置
saveEnabled = false
4.2 处理Fragment状态
// Fragment有自己的保存逻辑,记得在onViewStateRestored处理
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
// 这里才是Fragment恢复View状态的最佳位置
}
4.3 和ViewModel配合使用
- 轻量级数据用Bundle
- 复杂数据用ViewModel + onSaveInstanceState组合
// 典型用法:
class MyViewModel : ViewModel() {
// 临时数据
var tempData: String? = null
// 持久化数据
fun saveState(bundle: Bundle) {
bundle.putString("important_data", importantData)
}
fun restoreState(bundle: Bundle) {
importantData = bundle.getString("important_data")
}
}
五、灵魂拷问环节
Q:为什么有时候savedInstanceState是null?
A:两种情况:
- Activity第一次创建
- 系统明确要杀死你的进程(比如用户强制停止)
Q:能存多少数据?
A:实测超过500KB就开始有ANR风险,建议:
- 关键字段用基本类型
- 大文件走本地存储
- 用Room/DataStore持久化重要数据
Q:横竖屏切换保存的套路?
A:终极解决方案:
// 在Manifest里给Activity加这个
android:configChanges="orientation|screenSize|screenLayout"
// 然后重写onConfigurationChanged
// 但新手慎用!可能引发其他问题
六、总结 Checklist
✅ 只在onCreate判断是否为null
✅ 存/取使用相同的key
✅ 简单数据用Bundle,复杂数据用ViewModel+持久化
✅ 测试时多旋转屏幕
✅ 用adb命令模拟杀进程:
adb shell am kill com.example.package