本文译自:http://developer.android.com/training/basics/activity-lifecycle/recreating.html
由于一些通常的应用程序的行为,有些时候Activity会被销毁,如当用户按下Back按钮或调用finish()方法发出自我销毁信号的时候。如果Activity被终止,并且长时间不被使用时,或者前台的Activity要求更多的资源以致系统必须关掉后台进程来回收内存时,系统也可能会销毁你的Activity。
当你的Activity因为用户按下Back按钮或Activity调用自己的finish()方法被销毁时,系统会认为该Activity的实例一去不复返了,因为这种行为说明不在需要该Activity。但是,如果由于系统强制的原因导致Activity被销毁(而不是普通的行为),那么尽管该实际的Activity实例已经消失了,但是系统会记住它的存在,如果用户再次返回该Activity,那么系统就会使用一组它被销毁时保存下来的描述Activity的状态数据,来重建这个Activity。系统用于恢复之前状态的被保存的数据被叫做“实例状态”,并且它是一个保存在Bundle对象中的键-值对的集合。
警告:每次用户旋转屏幕时,你的Activity都会被销毁和重建。当屏幕改变方向时,因为屏幕配置的变化,并且你的Activity也可能需要加载另外的资源(如布局),所以系统会销毁并重建这个前台的Activity。
默认情况下,系统会使用Bundle实例来保存Activity布局中每个View对象的状态信息(如文本域中已经键入的文本值)。因此,如果你的Activity实例被销毁和重建,那么恢复之前的布局状态,不需你编写任何代码,但是,你的Activity可能还需要恢复更多的状态信息,如跟踪Activity中用户进度的成员变量。
注意:为了让Android系统能够恢复Activity中所有View的状态,每个View对象都必须有一个唯一的ID,这个ID是由android.id属性来提供的。
要保存有关Activity状态之外的数据,你必须重写onSaveInstanceState()回调方法。当用户离开你的Activity时,系统会调用这个方法,并把你要保存的数据传递给Bundle对象,这样数据就会在Activity被销毁时保存下来。如果系统以后必须要重建这个Activity,那么系统就会把这个Bundle对象传递给onRestoreInstanceState()和onCreate()方法。
图1.系统开始终止你的Activity时,它会调用onSaveInstanceState()(1)方法,因此你可以在这个回调方法中指定额外的你想要在重建时要恢复的状态数据。如果该Activity被销毁,并且相同的实例必须要被重建,那么系统就会把(1)中保存的状态数据传递给onCreate方法(2)和onRestoreInstanceState()方法(3)。
保存Activity的状态
当你的Activity开始执行终止处理时,系统会调用onSaveInstanceState()方法,因此你的Activity的状态能够把状态信息保存在一个键-值对的集合中。这个方法的默认实现会保存有关Activity中View层次的状态信息,如文本域中的文本,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()方法的超类的实现,以便默认的实现能够保存View层次的状态。
恢复Activity的状态
当你的Activity要从之前被销毁的状态中重建时,你可以从系统传给你的Activity的Bundle对象中恢复你保存的状态。onCreate()和onRestoreInstanceState()方法都会恢复包含在同一个Bundle对象中的实例状态信息。
因为onCreate()方法的调用要决定系统是创建一个新的Activity实例,还是从之前的状态中恢复一个Activity实例,所以在试图从Bundle对象读取信息之前,你必须检查Bundle对象是否是null,如果是null,那么系统就会创建一个新的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
}
...
}
与onCreate()方法执行期间恢复状态不同,你可以选择实现onRestoreInstanceState()方法,这个方法会在onStart()方法之后被系统调用。系统只会在有被保存的数据要恢复时,才会调用onRestoreInstanceState()方法,因此你不需要检查Bundle对象是否是null:
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);
}
警告:要始终调用onRestoreInstanceState()方法的超类的实现,以便默认实现能够恢复View层次的状态。