背景
如果系統(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);
}
畢。