Activity生命周期之重新创建(Recreating)一个Activity

2018年01月21日 08:54 | 586次浏览

有几个你的activity由于正常行为被销毁的场景,例如当用户点击了返回键,或者你的activity接收到自身调用 finish()方法发送的销毁信号。系统还可能会销毁那些被停止后长时间没有被使用到的activity,或者前台的activity需要更多的资源,系统会关闭后台进程来回收内存。


当你的activity由于用户点击返回键或者自己关闭而被销毁,这个Activity 实例在系统的概念上已经永远消失,因为这个行为表示这个activity不再被需要。然而,如果是由于系统限制(而不是普通的应用行为)导致系统销毁activity实例,那么即使Activity 实例已经消失,系统会记得它曾经存在过,所以当用户再次回到它时,系统会使用当时销毁activity时保存的数据集来为它重新创建一个实例。这个被系统使用来载入activity之前状态的数据集被称为"instance state" ,它是一个键值对的集合,被存储在一个Bundle 对象中。


注意: 每次用户切换横竖屏时你的activity都会被销毁然后重新创建。当屏幕方向改变时,系统销毁并重建前台activity是由于屏幕配置已经变化,你的activity可能需要加载另一个资源(例如布局)。


在默认情况下,系统使用Bundle instance state 来存放每个View对象的信息。因此,如果你的应用被销毁并重建,布局会被重新加载到之前的状态,不需要其他代码。然而,你的activity可能有更多的状态希望被重新载入,例如记录用户在activity中进程的成员变量。


提示: 为了让Android系统恢复你的activity中的view的状态,每个view都必须拥有一个唯一的ID,通过android:id 属性被指定。


为了保存关于activity状态的附加的数据,你必须覆盖onSaveInstanceState() 方法。当用户离开你的activity时系统会调用这个方法,通过它,当你的activity被异常销毁时Bundle 对象会被保存起来。如果系统之后必须重新创建activity实例,它会将相同的Bundle 对象同时传给onRestoreInstanceState() 和onCreate() 方法。

图 2. 当系统开始停止你的activity时,它会调用onSaveInstanceState() 

(1)方法,因此你可以指定你想要的数据保存起来。如果这个activity被销毁,那么当同样的实例被创建的时候,系统会将同样的状态数据同时传给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() 方法的父类的实现,这样默认的实现会保存view层次结构的状态。


恢复Activity的状态

当你的activity在销毁后被重建,你可以通过系统传递给你的Bundle 对象来恢复你所保存的状态。onCreate() 和onRestoreInstanceState() 会同时受到相同的包含状态信息的Bundle 对象。


由于onCreate() 方法在系统创建一个新的activity实例和重建activity实例时都会被调用,在你尝试使用状态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
    }
    ...
}

与其在在onCreate() 方法中恢复状态,你可以选择实现onRestoreInstanceState()方法,系统会在onStart() 方法后调用。系统只会在有保存的数据需要被恢复时才会调用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);
}

注意: 一定要调用onSaveInstanceState() 方法的父类的实现,这样默认的实现会保存view层次结构的状态。


感觉本站内容不错,读后有收获?小额赞助,鼓励网站分享出更好的教程