Android老司机带你搞懂onCreate里的savedInstanceState

在这里插入图片描述


一、这玩意儿到底是个啥?

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()会被自动调用,前提是:

  1. 设置了id(没id的View系统不知道你是谁)
  2. 不要设置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:两种情况:

  1. Activity第一次创建
  2. 系统明确要杀死你的进程(比如用户强制停止)

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jiet_h

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值