onSaveInstanceState()和onRestoreInstanceState()使用詳解

背景

如果系統由於系統約束(而不是正常的應用程序行爲)而破壞了Activity,那麼儘管實際 Activity實例已經消失,但是系統還是會記住它已經存在,這樣如果用戶導航回到它,系統會創建一個新的實例的Activity使用一組保存的數據來描述Activity在被銷燬時的狀態。系統用於恢復以前狀態的已保存數據稱爲“實例狀態”,是存儲在Bundle對象中的鍵值對的集合。

解決

onSaveInstanceState()和onRestoreInstanceState()就是這樣的背景下大展身手了。

注意
1、如果是用戶自動按下返回鍵,或程序調用finish()退出程序,是不會觸發onSaveInstanceState()和onRestoreInstanceState()的。
2、每次用戶旋轉屏幕時,您的Activity將被破壞並重新創建。當屏幕改變方向時,系統會破壞並重新創建前臺Activity,因爲屏幕配置已更改,您的Activity可能需要加載替代資源(例如佈局)。即會執行onSaveInstanceState()和onRestoreInstanceState()的。

介紹

默認情況下,系統使用Bundle實例狀態來保存有關View中Activity佈局每個對象的信息(例如輸入到EditText對象中的文本值)。因此,如果您的Activity實例被銷燬並重新創建,則佈局狀態會自動恢復到之前的狀態。但是,您的Activity可能包含更多要恢復的狀態信息,例如跟蹤Activity中用戶進度的成員變量。

爲了讓您爲Activity添加額外的數據到已保存的實例狀態,Activity生命週期中還有一個額外的回調方法,這些回調方法在前面的課程中沒有顯示。該方法是onSaveInstanceState(),系統在用戶離開Activity時調用它。當系統調用此方法時,它將傳遞Bundle將在您的Activity意外銷燬的事件中保存的對象,以便您可以向其中添加其他信息。然後,如果系統在被銷燬之後必須重新創建Activity實例,它會將相同的Bundle對象傳遞給您的Activity的onRestoreInstanceState()方法以及您的onCreate() 方法。

這是一個簡介圖

如上圖所示:
當系統開始停止您的Activity時,它會調用onSaveInstanceState()(1),以便您可以指定要保存的其他狀態數據,以防Activity必須重新創建實例。如果Activity被破壞並且必須重新創建相同的實例,則系統將(1)中定義的狀態數據傳遞給onCreate()方法(2)和onRestoreInstanceState()方法(3)。

保存你的Activity狀態

當您的Activity開始停止時,系統會調用,onSaveInstanceState()以便您的Activity可以使用一組鍵值對來保存狀態信息。此方法的默認實現保存有關Activity視圖層次結構狀態的信息,例如EditText小部件中的文本或ListView的滾動位置。

爲了保存Activity的附加狀態信息,您必須實現onSaveInstanceState()並向對象添加鍵值對Bundle。例如:

static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // 保存用戶自定義的狀態
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);

    // 調用父類交給系統處理,這樣系統能保存視圖層次結構狀態
    super.onSaveInstanceState(savedInstanceState);
}

恢復您的Activity狀態

當您的Activity在之前被破壞後重新創建時,您可以從Bundle系統通過您的Activity中恢復您的保存狀態。這兩個方法onCreate()和onRestoreInstanceState()回調方法都會收到Bundle包含實例狀態信息的相同方法。

因爲onCreate()調用該方法是否系統正在創建一個新的Activity實例或重新創建一個以前的實例,所以您必須Bundle在嘗試讀取之前檢查該狀態是否爲空。如果它爲空,那麼系統正在創建一個Activity的新實例,而不是恢復之前被銷燬的實例。

例如,下面是如何恢復一些狀態數據onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // 記得總是調用父類

    // 檢查是否正在重新創建一個以前銷燬的實例
    if (savedInstanceState != null) {
        // 從已保存狀態恢復成員的值
        mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
        mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else {
        // 可能初始化一個新實例的默認值的成員
    }
    ...
}

onCreate()您可以選擇執行onRestoreInstanceState(),而不是在系統調用onStart()方法之後恢復狀態。系統onRestoreInstanceState()只有在存在保存狀態的情況下才會恢復,因此您不需要檢查是否Bundle爲空:

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // 總是調用超類,以便它可以恢復視圖層次超級
    super.onRestoreInstanceState(savedInstanceState);

    // 從已保存的實例中恢復狀態成員
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

畢。

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