关于Android 的 onSaveInstanceState() 与 onRestoreInstanceState()

本文详细介绍了Activity中onSaveInstanceState()和onRestoreInstanceState()方法,用于状态的保存与恢复。onSaveInstanceState()不一定被触发,主动销毁Activity时不调用;触发它也不一定触发onRestoreInstanceState()。保存和恢复View层次结构基于委托思想,Activity委托Window,Window委托顶级容器,顶级容器通知子View。

参考文章:onSaveInstanceState 和 onRestoreInstanceState详解


onSaveInstanceState()onRestoreInstanceState() 是关于 Activity 中状态的保存与恢复的方法。

当然在 View 中也存在这一组方法,而 Fragment 则比较特殊,只有 onSaveInstanceState() 而没有 onRestoreInstanceState()(可以参阅 [译]Android Activity 和 Fragment 状态保存与恢复的最佳实践 进一步了解)。

而实际上,Activity 中 onSaveInstanceState()onRestoreInstanceState() 的实现(以及 Fragment 中的 onSaveInstanceState())就是基于 View 的对应的那一组方法实现的。


在自己的 Activity 中,可以重写那一组方法,用于实现自身需要的状态的保存与恢复。

需要注意的是:
1、super.onSaveInstanceState(outState) 会默认实现自动保存 Activity 中的某些状态数据,如 UI 控件的状态等,比如一个 EditText,输入了某些内容,这些内容会在必要的时机被保存下来。

2、super.onRestoreInstanceState(savedInstanceState) 则实现了自动恢复在 super.onSaveInstanceState(outState) 中保存的状态数据,如前面说的 EditText 中输入的被保存的内容。

注意!注意!注意!这里说的是父类的对应的方法。如果在自己的 Activity 中没有调用父类的方法,则无法实现 Activity 中某些状态数据的保存与恢复。

且实现上述两点的前提是需要为 View 设置 id 属性。


(1) onSaveInstanceState() 并不一定被触发

onSaveInstanceState() 的调用遵循一个重要原则,即当 系统存在 “未经你许可” 时销毁我们的 activity 的可能 时,则onSaveInstanceState() 会被系统调用。这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然是否把握机会保存则是由开发者自行把握)。

被调用的时机可能发生在 onPause() 或者 onStop() 之前。但是通常情况下是在 onPause() 和 onStop() 之间调用。

但是当用户主动去销毁一个 Activity 时,例如在应用中按返回键,onSaveInstanceState() 就不会被调用。因为在这种情况下,用户的行为决定了不需要保存 Activity 的状态。

onSaveInstanceState() 会被调用的几种情景:

(1)、当用户按下HOME键时。
(2)、长按HOME键,选择运行其他的程序时。
(3)、按下电源按键(关闭屏幕显示)时。
(4)、从 activity A 中启动一个新的 activity 时。
(5)、屏幕方向切换时,例如从竖屏切换到横屏时。
(6)、更改设备语言等。

onSaveInstanceState() 只适合用于保存一些临时性的状态,而 onPause() 适合用于数据的持久化保存。

(2) 触发了 onSaveInstanceState() ,也不一定会触发 onRestoreInstanceState()

因此 Activity 不一定有被系统销毁重建。

但是触发了 onRestoreInstanceState(),前提一定是有通过 onSaveInstanceState() 保存了数据(准确的说是生成并保存了对应的 bundle 实例,这里的 bundle 的实例化与保存是在系统源码中实现的)。

如果触发了 onRestoreInstanceState(bundle),则在 onCreate(bundle) 中也会传递对应的 bundle 实例(即此时 onCreate() 方法传递来的 bundle 不为空)。

且 onCreate() 和 onRestoreInstanceState() 中传递过来的 Bundle 实例是同一个。

(3) 关于保存和恢复 View 层次结构

Activity#onSaveInstanceState() 被触发,保存 View 层次结构的内容时,Activity 会委托 Window 去保存数据,接着 Window 再委托它上面的顶级容器去保存数据,顶级容器是一个 ViewGroup,一般来说很有可能是 DecorView。最后顶级容器再一一通知子 View 来保存数据。

基于委托的思想。

是的,你理解得基本正确: 在 Android 中,**`onSaveInstanceState()` 和 `onRestoreInstanceState()` 只会在“**非正常销毁和重建**”的场景下被触发**。 --- ## ✅ 什么是“异常销毁”? Android 中的 **异常销毁**,指的是系统**主动销毁并重建 Activity** 的情况,通常是由于系统资源不足或配置变更(如横竖屏切换)导致的。 ### 常见异常销毁场景包括: | 场景 | 是否触发 onSaveInstanceState/onRestoreInstanceState | |------|--------------------------------------------------------| | 横竖屏切换(配置变更) | ✅ 是 | | 系统资源不足,后台 Activity 被杀死 | ✅ 是 | | 用户按下 Home 键后系统回收进程 | ✅ 是 | | 用户按下返回键关闭 Activity | ❌ 否 | | 主动调用 `finish()` | ❌ 否 | | 用户按下电源键休眠设备 | ✅ 是(取决于系统行为) | --- ## ✅ 方法详解 ### 📌 1. `onSaveInstanceState(Bundle outState)` - **调用时机**:在 Activity 被销毁前调用(仅在异常销毁时)。 - **作用**:保存 UI 状态或临时数据。 - **示例**: ```java @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString("key", "value"); } ``` ### 📌 2. `onRestoreInstanceState(Bundle savedInstanceState)` - **调用时机**:在 `onStart()` 之后调用,仅在 Activity 被重建时触发。 - **作用**:恢复之前保存的状态。 - **示例**: ```java @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); String value = savedInstanceState.getString("key"); } ``` --- ## ✅ `onCreate()` 的关系 `onCreate()` 中也可以恢复状态: ```java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { String value = savedInstanceState.getString("key"); } } ``` > 所以,**`onRestoreInstanceState()` 是对 `onCreate()` 恢复状态的补充**,适合恢复 UI 相关的状态。 --- ## ✅ 开发建议 | 场景 | 推荐做法 | |------|----------| | 正常跳转 Activity | 不需要保存状态,使用 Intent 传值 | | 横竖屏切换 | 使用 `onSaveInstanceState()` 保存 UI 状态 | | 进程被杀死重建 | 使用 `onRestoreInstanceState()` 恢复数据 | | 避免保存大量数据 | Bundle 有大小限制(建议 < 1MB) | | 保存复杂对象 | 使用 `Parcelable` 或 `Serializable` | --- ## ✅ 示例代码 ```java public class MainActivity extends AppCompatActivity { private static final String KEY_TEXT = "text"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState != null) { String text = savedInstanceState.getString(KEY_TEXT); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString(KEY_TEXT, "Hello"); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); String text = savedInstanceState.getString(KEY_TEXT); } } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值