重新创建一个activity
翻译自官方文档API21
在少数几种情况下,你的activity会因为APP的普通行为而被销毁,比如用户按了返回按钮或者activity自己在析构函数中调用了finish()方法。当你的activity目前处于停止状态并且长时间都没有被使用,或者是前台activity需要更多的系统资源而需要关闭后台的进程来释放内存时,系统也会销毁你的activity。
当你的activity是因为用户按了返回按钮而终结自己时,系统就会觉得这个activity实例永远都不会存在了因为这个动作就意味着这个activity已经不是必须的了。但是,是因为系统约束(而不是APP的普通行为)导致这个activity被销毁,尽管这个activity实例已经不存在,系统却记得它曾经存在过,这样,如果用户再次通过导航回到它,系统会通过销毁它时保留下来的状态数据创建一个新的实例。这些被保存的,系统用来恢复之前状态的数据被叫做实例状态(instance state),它时存在Bundle对象中的键值对的集合。
注意:用户每次旋转屏幕时,你的activity都会被销毁和重新创建。当屏幕改变方向时,系统会销毁并重新创建前台activity,因为屏幕配置已经改变,你的activity可能需要加载替代资源(比如布局)。
默认情况下,系统在你的activity布局(比如EditText对象中输入的文本值)中使用Bundle实例来存储每个视图的信息。所以,如果你的activity被销毁并重现创建,你不必用代码来把布局恢复到之前的状态。但是,你的activity中可能会有更多你想要存储的状态信息,比如activity中追踪用户进度的成员变量。
Note:为了让Android系统存储你的activity中每个视图(View)的状态,每个视图必须拥有一个唯一的ID,通过android:id属性来实现。
为了保存有关activity状态的额外变量,你必须重写onSavedInstanceState()方法。当用户离开你的activity时,系统会调用这个方法,并把它传给Bundle对象,而Bundle对象会在activity被意外销毁时被保存下来。如果系统稍后必须必须重新创建这个activity实例,它会把同一个Bundle对象传给onRestoreInstabceState()和onCreate()方法。
图2当系统开始停止你的activity时,它调用onSaveInstanceState()(1),所以你必须你想要保存的额外数据,以防activity实例被重新创建。如果activity被销毁并且同一个实例必须被重新创建,系统会把定义在(1)中的状态数据同时传给onCreate()方法(2)和onRestoreInstanceState()方法(3).
保存你的activity状态
由于你的activity开始停止时,系统调用onSaveInstanceState()方法,所以activity的状态信息会以键值对集合的方式保存下来。这个方法默认保存了有关activity实例中View层次结构的信息,比如在EditText组件中的文本或ListView的滚动位置。
要保存你的activity的额外状态信息,你必须实现onSaveInstanceState()方法并向Bundle对象中存入键值对。举例:
static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
注意:总是调用父类的onSaveInstanceState()方法,这样可以保证默认的实现方法可以保存视图不同层次的状态。
恢复你的Activity
你的activity之前已经被销毁,当它被重新创建时,你可以从系统传给你的Bundle对象中恢复之前保存的状态。onCreate()方法和onRestoreInstanceState()方法都会接收到同一个Bundle对象,这个对象包含着实例的状态信息。
不管新建一个activity实例还是从根据之前的实例重新创建一个,系统都会调用onCreate()方法,你必须在读取Bundle之前检查一下它是否为空。如果它为空,系统会重新创建一个activity实例,而不是根据之前被销毁的实例恢复一个实例。
举例说明,这里展示了怎么在onCreate()中恢复一些状态。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
...
}
系统会在onStart()方法之后调用onRestoreInstanceState()方法,你可能会选择实现这个方法而不是在onCreate()方法中恢复状态。仅当有被保存的状态时,系统才会调用onRestoreInstanceState()方法,所以你不必检查Bundle对象是否为空。
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);
// Restore state members from saved instance
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}