翻译自官方文档:Receating an Activity
更透彻的关于onSaveInstanceState()函数保存数据,onRestoreInstanceState()函数和onCreate()函数恢复数据的整个流程及源代码理解请参考博文:深入理解onSaveInstanceState & onRestoreInstanceState 方法
Activity在以下几种情况下由于正常的应用操作会被销毁,例如:当用户按下后退键或者是Activity本身调用了finish()方法。此外,如果你的Activity生命周期处于stop状态而且一段时间内都没有被调用或者是处于前台的Activity需要更多的资源而系统资源紧张的时候,系统也会销毁你的Activity,杀掉后台进程给前台进程留出足够的内存。
当你的Activity由于用户按下后退键或者是Activity本身调用了finish()方法时,系统认为该Activity将会永远消失,因为前面两种情况表明该Activity不再被需要。然而,如果系统由于本身的限制不得不销毁Activity而不是应用本身的行为销毁Activity,尽管该Activity已经消失,但是系统仍然记得它。只要用户重新进入该Activity,系统就会利用系统自己销毁该Activity时保存的一些描述该Activity状态的数据来重新创建一个新的Activity。这些系统用于恢复之前Activity状态而保存的数据叫做“实例状态”,它本质上是一些键值对,并保存在Bundle对象中。
警告:当用户进行横竖屏切换的时候,你的应用的当前Activity机会被销毁和重建。当屏幕更改方向时,由于屏幕的改变,当前Activity需要重新加载交互资源,必须布局资源,此时系统就会销毁和重建前台Acitvity。
默认情况下,系统使用Bundle实例状态来保存你的Activity中的View对象的信息,比如 EditText 可编辑框中输入的数据。所以,如果你的Activity被销毁和重建,你的布局资源的状态会保存当前被销毁的Activity的状态,而这些并不用你自己编写代码实现。然而,你自己本身可能会有想要保存的数据,比如当前要被销毁的Activity中的一些变量的值。
注解:为了android熊够恢复你的Activity的一些View的状态,每一个要保存的View必须包含唯一的ID,这个ID 就是我们在xml文件中定义是所写的 android:id 这个属性。
为了保存一些这个被销毁的Acitvity的额外数据,你必须复写 onSaveInstanceState() 回调函数。当用户将要离开这个Activity的时候,系统就会调用这个回调函数,并且传递 给它一个Bundle对象作为参数,当你的activity被突然销毁时,这个Bundle对象就会保存该Activity的一些状态值,其他情况下该Bundle的值均为null。如果系统之后必须恢复activity实例,它就会传递刚刚保存被销毁的Activity的实例状态这个Bundle对象给onRestoreInstanceState()方法和onCreate()方法。
如上图:当系统要停止你的Activity的时候,系统会调用onSaveInstanceState()方法,所以你可以添加你想保存的额外状态数据以防止Activity被销毁重建。如果activity被销毁而且要重建一个相同的activity实例,系统就会传递之前保存的状态数据(保存在Bundle中)给onCreate()方法和onRestoreInstanceState()方法。
保存Activity状态
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数据
@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
}
...
}
你应该选择复写实现onRestoreInstanceState()方法,这个方法是在onStart()方法之后被调用的,而不是选择实现onCreate()方法去恢复数据。系统只有当保存了状态数据要恢复的时候才会调用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);
}
警告:复写该方法时要调用该方法的父类实现,默认的实现方法才会保存该Activity的阶级视图。