Activity生命週期詳解(四)

四、重新創建activity
有幾個場景中,activity是由於正常的程序行爲而被Destroy的,例如當用戶點擊返回按鈕或是activity通過調用finish()來發出停止信號。系統也有可能會在activity處於stop狀態且長時間不被使用,或是在前臺activity需要更多系統資源時關閉後臺進程,以圖獲取更多的內存。

當activity是因爲用戶點擊Back按鈕或是activity通過調用finish()結束自己時,系統就會丟失了對activity實例的引用,因爲這一行爲意味着不再需要這個activity了,然而,如果因爲系統資源緊張而導致activity的Destroy,系統會在用戶回到這個activity時有這個activity存在過的記錄,系統會使用那些保存的記錄數據(描述了當activity被Destroy時的狀態)來重新創建一個新的activity實例,那些被系統用來恢復之前狀態而保存的數據叫做“instance state”, 它是一些存放在Bundle對象中的key-values pairs(請注意這裏的描述,這對理解onSaveInstanceState執行時刻很重要)

Caution:你的activity會在每次旋轉屏幕時被destroyed與recreated。當屏幕改變方向時,系統會Destroy與Recreate前的activity,因爲屏幕配置的改變,你的activity可能需要加載另一些替代的資源(例如layout)

默認情況下,系統使用Bundle實例來保存每一個View(視圖)對象中的信息(例如輸入EditText中的文本內容)
因此,如果activity被destroyed與recreated,則layout的狀態信息會自動回覆到之前的狀態。然而,activity也許存在更多你想要恢復的狀態信息,例如,記錄用戶Progress的成員變量(member variables)

Note: 爲了使Android系統能夠恢復activity中的View狀態,每個View都必須有一個唯一ID。由android:id定義

爲了可以保存額外更多的數據到saved instance state。在activity的生命週期裏面存在一個額外的回調函數,你必須重寫這個函數。該回調函數並沒有在前面課程的圖片示例中顯示,這個方法是onSaveInstanceState(),當用戶離開activity時,系統會調用它。當系統調用這個函數時,系統會在activity被異常Destroy時傳遞Bundle對象,這樣我們就可以增加額外的信息到Bundle中並保存到系統中,若系統在activity被Destroy之後,onRestoreInstanceState()方法與onCreate()方法中

這裏寫圖片描述

Figure2. 當系統開始停止activity時,只有在activity實例會需要重新創建的情況下才會調用到onSaveInstanceState(1)。在這個方法裏面可以指定額外的狀態數據到Bundle中如果這個activity被destroyed然後這個實例又需要被重新創建時,系統會傳遞在(1)中的狀態數據到onCreate(2)與onRestroreInstanceState(3)
( 通常來說,跳轉到其它的activity或點擊Home都會導致當前的activity執行onSaveInstanceState,因爲這種情況下的activity都是有可能會被destroy並且是需要保存狀態以便後續恢復使用 ,而從跳轉的activity點擊back回到前一個activity,那麼跳轉的activity是執行退棧的操作,所以這種情況下是不會執行onSaveInstanceState的,因爲這個activity不可能存在需要重建的操作)

2.保存activity狀態

當我們的activity開始stop,系統會調用onSaveInstanceState(), activity可以用鍵值對的集合來保存狀態信息。這個方法會默認保存activity視圖的狀態信息,如在EditText組件中的文本或ListView的滑動位置。

爲了給activity保存額外的狀態信息,你必須實現onSaveInstanceState()並增加key-value pairs到Bundle對象中,例如:

staticfinal String STATE_SCORE = "playerScore";
staticfinal String STATE_LEVEL = "playerLevel";
...

@Override
public void onSaveInstanceState(Bundle savedInstanceState){
    // Save the user current 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);
}

Cauthion:必須要調用onSaveInstanceState()方法的父類實現,這樣默認的父類實現才能保存視圖狀態的信息。

3.恢復activity狀態

當activity從Destroy中重建,我們可以從系統傳遞的activity的Bundle中恢復保存的狀態。onCreate()與onRestoreInstanceState()回調方法都接收到了同樣的Bundle,裏面包含了同樣的實例狀態信息。

由於onCreate()方法會在第一次創建新的activity實例與重新創建之前被Destroy的實例時被調用,我們必須在嘗試讀取Bundle對象前檢測它是否爲null。如果它爲null,系統則是創建一個新的activity實例,而不是恢復之前被Destroy的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
    }
    ...
}

我們也可以選擇實現onRestoreInstanceState(),而不是在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);
}

Caution:與上面保存一樣,總是需要調用onRestoreInstanceState()方法的父類實現,這樣默認的父類實現才能保存視圖狀態的信息。更多關於運行時狀態改變引起的recreate我們的activity。請參考 Handling Runtime Changes

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章