《savedinstancestate吐血详解 - 副本》由会员分享,可在线阅读,更多相关《savedinstancestate吐血详解 - 副本(5页珍藏版)》请在金锄头文库上搜索。
1、Activity 的生命周期里并没有提到 onSaveInstanceState 的触发,这个函数提供了为我们在某些情况下保存 Activity 信息的机会,但需要注意的是这个函数不是什么时候都会被调用的,官方文档解释的比较清楚,特此 翻译一下。 在 activity 被杀掉之前调用保存每个实例的状态, 以保证该状态可以在 onCreate(Bundle)或者 onRestoreInstanceState(Bundle) (传入的 Bundle 参数是由 onSaveInstanceState 封装好的) 中恢复。这个方法在一个 activity 被杀死前调用,当该 activity 在将来某
2、个时刻回来时可以恢复其先前状态。例如,如果 activity B 启用后位于 activity A 的前端,在某个时刻activity A 因为系统回收资源的问题要被杀掉, A 通过 onSaveInstanceState将有机会保存其用户界面状态,使得将来用户返回到 activity A 时能通过onCreate(Bundle)或者 onRestoreInstanceState(Bundle)恢复界面的状态。不要将这个方法和 activity 生命周期回调如 onPause()或 onStop()搞混淆了,onPause()在 activtiy 被放置到背景或者 自行销毁时总会被调用,onS
3、top()在activity 被销毁时被调用。一个会调用 onPause()和 onStop(),但不触发 onSaveInstanceState 的例子是当用户从 activity B 返回到 activity A 时:没有必要调用 B 的 onSaveInstanceState(Bundle),此时的 B 实例永远不会被恢复,因此系统会避免调用它。一个调用 onPause()但不调用onSaveInstanceState 的例子是当 activity B 启动并处在 activity A 的前端:如果在 B 的整个生命周期里 A 的用户界面状态都没有被破坏的话,系统是不会调用activit
4、y A 的 onSaveInstanceState(Bundle)的。 默认的实现负责了大部分UI 实例状态(的保存),采用的方式是调用 UI 层上每个拥有 id 的 view 的onSaveInstanceState() ,并且保存当前获得焦点的 view 的 id(所有保存的状态信息都会在默认的 onRestoreInstanceState(Bundle)实现中恢复) 。 如果你覆写这个方法来保存额外的没有被各个 view 保存的信息,你可能想要在默认实现过程中调用或者自己保存每个视图的所有状态。如果被调用,这个方法会 在 onStop()前被触发,但系统并不保证是否在 onPause()
5、之前或者之后触发。 很多不明白Activity 类中包含的 onSaveInstanceState 和onRestoreInstanceState 有什么用,首先声 明下使用这两个方法时一定要注意情况和了解 Activity 的生命周期,否则有的时候 onSaveInstanceState 和 onRestoreInstanceState 可能不会被触发,虽然他们都是 Activity 的重写方法。 (文/Android 开发网) 他们比较常用到的地方是 Sensor、Land 和 Port 布局的自动切换,过去Android 开发网曾经说过解决横屏和竖屏切换带来的数据被置空或者说 onCre
6、ate 被重复调 用问题,其实 Android 提供的onSaveInstanceState 方法可以保存当前的窗口状态在即将布局切换前或当前 Activity 被推入历史 栈,其实布局切换也调用过 onPause所以被推入 Activity 的 history stack,如果我们的 Activity 在后台没有因为运行内存吃紧被清理,则切换回时会触发onRestoreInstanceState 方法。 这两个方法中参数均为 Bundle,可以存放类似 SharedPreferences 的数据,所以使用它们作为当前窗口的状态保存是比较合适的。实际使用代码 从这句话可以知道,当某个 acti
7、vity 变得“容易 ”被系统销毁时,该 activity 的onSaveInstanceState 就会被执行,除非该 activity 是被用户主动销毁的,例如当用户按 BACK 键的时候。 注意上面的双引号,何为“容易”?言下之意就是该 activity 还没有被销毁,而仅仅是一种可能性。这种可能性有哪些?通过重写一个 activity 的所有生命周期的 onXXX方法,包括 onSaveInstanceState 和 onRestoreInstanceState 方法,我 们可以清楚地知道当某个 activity(假定为 activity A)显示在当前 task 的最上层时,其 on
8、SaveInstanceState 方法会在什么时候被执行,有这么几种情况: 1、当用户按下 HOME 键时。这是显而易见的,系统不知道你按下 HOME 后要运行多少其他的程序,自然也不知道 activity A 是否会被销毁,故系统会调用 onSaveInstanceState,让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则 2、长按 HOME 键,选择运行其他的程序时。 3、按下电源按键(关闭屏幕显示)时。 4、从 activity A 中启动一个新的 activity时。 5、屏幕方向切换时,例如从竖屏切换到横屏时。在屏幕切换之前,系统会销毁 activity A,在
9、屏幕切换之后系统又会自动地创建activity A,所以 onSaveInstanceState 一定会被执行 总而言之,onSaveInstanceState 的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的 activity,则 onSaveInstanceState 会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了) 。 开启应用-back 键一下(此时回到手机主界面,但是还在任务栏中)点击任务栏中的程序 11-27 15:40:19.245: I/hhhd(28366): onCreate 11-27 15:40:19.268:
10、 I/hhhd(28366): onStart 11-27 15:40:19.268: I/hhhd(28366): onResume 11-27 15:40:20.674: I/hhhd(28366): onPause 11-27 15:40:21.142: I/hhhd(28366): onStop 11-27 15:40:21.143: I/hhhd(28366): onDestroy 11-27 15:40:22.902: I/hhhd(28366): onCreate 11-27 15:40:22.931: I/hhhd(28366): onStart 11-27 15:40:22.
11、931: I/hhhd(28366): onResume 开启应用-home 键一下(此时回到手机主界面,但程序还在任务栏中)-点击任务栏中的程序 11-27 15:58:30.204: I/hhhd(29984): onCreate 11-27 15:58:30.232: I/hhhd(29984): onStart 11-27 15:58:30.233: I/hhhd(29984): onResume 11-27 15:58:33.667: I/hhhd(29984): onPause 11-27 15:58:34.192: I/hhhd(29984): onSaveInstanceSta
12、te 11-27 15:58:34.192: I/hhhd(29984): onStop 11-27 15:58:37.466: I/hhhd(29984): onStart 11-27 15:58:37.467: I/hhhd(29984): onResume 只要 Activity 不 finish,Activity 进入后台(比如 Home 键,跳转到其他的 Activity) ,则其就会调用onSaveInstanceState(Bundle outState)方法, 而且这个方法是在onPause 方法和 onStop 之间进行调用的。 如果 Activity 是执行了finish
13、方法(相当于点击了回退键) ,才进入的后台,则不调用这个onSaveInstanceState(Bundle outState), 而且下次再进入时,也不会使用这个保存的数据。 当切换横竖屏幕 11-27 16:44:54.464: I/hhhd(2080): onPause 11-27 16:44:54.464: I/hhhd(2080): onSaveInstanceState 11-27 16:44:54.465: I/hhhd(2080): onStop 11-27 16:44:54.465: I/hhhd(2080): onDestroy 11-27 16:44:54.555: I/
14、hhhd(2080): onCreate 11-27 16:44:54.594: I/hhhd(2080): -dfsdaf /保存在 savedInstanceState 的数据 11-27 16:44:54.602: I/hhhd(2080): onStart 11-27 16:44:54.602: I/hhhd(2080): onRestoreInstanceState 11-27 16:44:54.615: I/hhhd(2080): onResume 当锁定屏幕: 11-27 16:47:25.910: I/hhhd(2502): onPause 11-27 16:47:25.919
15、: I/hhhd(2502): onSaveInstanceState 11-27 16:47:25.919: I/hhhd(2502): onStop 当解锁屏幕: 11-27 16:48:26.956: I/hhhd(2782): onStart 11-27 16:48:26.959: I/hhhd(2782): onResume 当来电时: 11-27 08:59:30.194: I/hhhd(1784): onPause 11-27 08:59:30.894: I/hhhd(1784): onSaveInstanceState 11-27 08:59:30.894: I/hhhd(1784): onStop 我们都知道 Activity 是存在栈中的,实行后进先出的原则,那么当一个新的 Activity B 覆盖在 Activity A 之上时候,A 就会调用 onSaveInstanceState 方法保存 A 里面 UI 的状态,当然,你也可以添加一个自定义需要保存的东西放在 bundle 中,当发生一些事件(比如 切换屏幕 , )会从 onCreate 中把 bundle 里面的 UI 状态或者上面保存的东西提取出来