一、
先看Application Fundamentals上的一段话:
Android calls onSaveInstanceState() before the activity becomes vulnerable to being destroyed by the system, but does not bother calling it when the instance is actually being destroyed by a user action (such as pressing the BACK key)
从这句话可以知道,当某个activity变得“容易”被系统销毁时,该activity的onSaveInstanceState就会被执行,除非该activity是被用户主动销毁的,例如当用户按BACK键的时候。
注意上面的双引号,何为“容易”?言下之意就是该activity还没有被销毁,而仅仅是一种可能性。这种可能性有哪些?通过重写一个activity的所有生命周期的onXXX方法,包括onSaveInstanceState和onRestoreInstanceState方法,我们可以清楚地知道当某个activity(假定为activity A)显示在当前task的最上层时,其onSaveInstanceState方法会在什么时候被执行,有这么几种情况:
1、当用户按下HOME键时。
这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,故系统会调用onSaveInstanceState,让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则
2、长按HOME键,选择运行其他的程序时。
3、按下电源按键(关闭屏幕显示)时。
4、从activity A中启动一个新的activity时。
5、屏幕方向切换时,例如从竖屏切换到横屏时。
在屏幕切换之前,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState一定会被执行
总而言之,onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)。
至于onRestoreInstanceState方法,需要注意的是,onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成对的被调用的,onRestoreInstanceState被调用的前提是,activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执行
另外,onRestoreInstanceState的bundle参数也会传递到onCreate方法中,你也可以选择在onCreate方法中做数据还原
二、
1 The system calls this method before making the activity vulnerable to being destroyed and passes it a Bundle
object. The Bundle
is where you can store state information about the activity as name-value pairs, using methods such as putString()
. Then, if the system kills your activity's process and the user navigates back to your activity, the system passes the Bundle
to onCreate()
so you can restore the activity state you saved during onSaveInstanceState()
. If there is no state information to restore, then the Bundle
passed to onCreate()
is null.
一般onSaveInstanceState(Bundle ) 和 onCreate(Bundle ) 结合使用来保存activity的状态,但是文档里面指出了几个问题:系 统不会保证onSaveInstanceState()在activity被销毁前总被调用(因为有一些不需要保存状态的情况,比如,用户用BACK键关 闭此activity);如果onSaveInstanceState()被调用,那么一定是在onStop()之前,或者可能在onPause()之 前。
2 如果你在onSaveInstanceState()不做啥事(不重载它),有些activity的状态也会被activity默认的 onSaveInstanceState()保存。比如,通常EditText会保存自己的状态,原因就是activity默认的 onSaveInstanceState()会调用其layout里面每一个View的onSaveInstanceState(),当然也包括此 EditView。你只需要为这些view提供唯一的ID(android:id属性),他们就会保存自己的状态,不用你操心了。这个自动保存可以通过 android:saveEnabled属性或者 setSaveEnabled()方法 来禁用。
3 “onSaveInstanceState() 只应该被用来保存activity暂时的状态(例如,类成员变量的值关联着UI),而不应该用来保存持久化数据。持久化数据应该当用户离开当前的 activity时,在 onPause() 中保存(比如,保存到数据库)。” 这里用onPause()令我不理解,因为文档前面提过,onPause()时,activity并没有完全看不到,而只是可能有个dialog盖住 它,所以不建议在onPause()中做耗时的工作。(这里我只能将写入数据库理解为轻量级操作了。。。。暂时我觉得持久化数据应该在 onDestroy()中做)。
4 可以用旋转屏幕来测试你的程序保存状态的能力。因为一般旋转时,activity会被重新 onCreate() onStart()等等,程序此时能够保存状态是很重要的。
三、
1 利用onSaveInstanceState()保存数据:
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt("flag", flag);
outState.putString("menu", this.menu);
outState.putString("shop", shop);
outState.putInt("editPosition", editPosition);
super.onSaveInstanceState(outState);
}
2 在onCreate方法中做数据还原
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (savedInstanceState != null) {
this.flag = savedInstanceState.getInt("flag");
this.editPosition = savedInstanceState.getInt("editPosition");
String menu = savedInstanceState.getString("menu");
if (!TextUtils.isEmpty(menu)) {
this.menu = menu;
}
String shop = savedInstanceState.getString("shop");
if (!TextUtils.isEmpty(shop)) {
this.shop = shop;
}
}