onSaveInstanceState()和onRestoreInstanceState()使用詳解

背景

如果系統(tǒng)由于系統(tǒng)約束(而不是正常的應(yīng)用程序行為)而破壞了Activity,那么盡管實際 Activity實例已經(jīng)消失,但是系統(tǒng)還是會記住它已經(jīng)存在,這樣如果用戶導(dǎo)航回到它,系統(tǒng)會創(chuàng)建一個新的實例的Activity使用一組保存的數(shù)據(jù)來描述Activity在被銷毀時的狀態(tài)。系統(tǒng)用于恢復(fù)以前狀態(tài)的已保存數(shù)據(jù)稱為“實例狀態(tài)”,是存儲在Bundle對象中的鍵值對的集合。

解決

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

注意
1、如果是用戶自動按下返回鍵,或程序調(diào)用finish()退出程序,是不會觸發(fā)onSaveInstanceState()和onRestoreInstanceState()的。
2、每次用戶旋轉(zhuǎn)屏幕時,您的Activity將被破壞并重新創(chuàng)建。當(dāng)屏幕改變方向時,系統(tǒng)會破壞并重新創(chuàng)建前臺Activity,因為屏幕配置已更改,您的Activity可能需要加載替代資源(例如布局)。即會執(zhí)行onSaveInstanceState()和onRestoreInstanceState()的。

介紹

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

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

這是一個簡介圖

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

保存你的Activity狀態(tài)

當(dāng)您的Activity開始停止時,系統(tǒng)會調(diào)用,onSaveInstanceState()以便您的Activity可以使用一組鍵值對來保存狀態(tài)信息。此方法的默認實現(xiàn)保存有關(guān)Activity視圖層次結(jié)構(gòu)狀態(tài)的信息,例如EditText小部件中的文本或ListView的滾動位置。

為了保存Activity的附加狀態(tài)信息,您必須實現(xiàn)onSaveInstanceState()并向?qū)ο筇砑渔I值對Bundle。例如:

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

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // 保存用戶自定義的狀態(tài)
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
    
    // 調(diào)用父類交給系統(tǒng)處理,這樣系統(tǒng)能保存視圖層次結(jié)構(gòu)狀態(tài)
    super.onSaveInstanceState(savedInstanceState);
}

恢復(fù)您的Activity狀態(tài)

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

因為onCreate()調(diào)用該方法是否系統(tǒng)正在創(chuàng)建一個新的Activity實例或重新創(chuàng)建一個以前的實例,所以您必須Bundle在嘗試讀取之前檢查該狀態(tài)是否為空。如果它為空,那么系統(tǒng)正在創(chuàng)建一個Activity的新實例,而不是恢復(fù)之前被銷毀的實例。

例如,下面是如何恢復(fù)一些狀態(tài)數(shù)據(jù)onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // 記得總是調(diào)用父類
   
    // 檢查是否正在重新創(chuàng)建一個以前銷毀的實例
    if (savedInstanceState != null) {
        // 從已保存狀態(tài)恢復(fù)成員的值
        mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
        mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else {
        // 可能初始化一個新實例的默認值的成員
    }
    ...
}

onCreate()您可以選擇執(zhí)行onRestoreInstanceState(),而不是在系統(tǒng)調(diào)用onStart()方法之后恢復(fù)狀態(tài)。系統(tǒng)onRestoreInstanceState()只有在存在保存狀態(tài)的情況下才會恢復(fù),因此您不需要檢查是否Bundle為空:

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // 總是調(diào)用超類,以便它可以恢復(fù)視圖層次超級
    super.onRestoreInstanceState(savedInstanceState);
   
    // 從已保存的實例中恢復(fù)狀態(tài)成員
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

畢。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容