Android重新創(chuàng)建Activity

2018-08-02 18:34 更新

編寫:kesenhoo - 原文: http://developer.android.com/training/basics/activity-lifecycle/recreating.html

有幾個場景中,Activity是由于正常的程序行為而被Destory的。例如當用戶點擊返回按鈕或者是Activity通過調(diào)用finish()來發(fā)出停止信號。系統(tǒng)也有可能會在Activity處于stop狀態(tài)且長時間不被使用,或者是在前臺activity需要更多系統(tǒng)資源的時關閉后臺進程,以圖獲取更多的內(nèi)存。

當Activity是因為用戶點擊Back按鈕或者是activity通過調(diào)用finish()結束自己時,系統(tǒng)就丟失了對Activity實例的引用,因為這一行為意味著不再需要這個activity了。然而,如果因為系統(tǒng)資源緊張而導致Activity的Destory, 系統(tǒng)會在用戶回到這個Activity時有這個Activity存在過的記錄,系統(tǒng)會使用那些保存的記錄數(shù)據(jù)(描述了當Activity被Destory時的狀態(tài))來重新創(chuàng)建一個新的Activity實例。那些被系統(tǒng)用來恢復之前狀態(tài)而保存的數(shù)據(jù)被叫做 "instance state" ,它是一些存放在Bundle對象中的key-value pairs。(請注意這里的描述,這對理解onSaveInstanceState執(zhí)行的時刻很重要)

Caution: 你的Activity會在每次旋轉(zhuǎn)屏幕時被destroyed與recreated。當屏幕改變方向時,系統(tǒng)會Destory與Recreate前臺的activity,因為屏幕配置被改變,你的Activity可能需要加載另一些替代的資源(例如layout).

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

Note: 為了使Android系統(tǒng)能夠恢復Activity中的View的狀態(tài),每個View都必須有一個唯一ID,由android:id定義。

為了可以保存額外更多的數(shù)據(jù)到saved instance state。在Activity的生命周期里面存在一個額外的回調(diào)函數(shù),你必須重寫這個函數(shù)。該回調(diào)函數(shù)并沒有在前面課程的圖片示例中顯示。這個方法是onSaveInstanceState() ,當用戶離開Activity時,系統(tǒng)會調(diào)用它。當系統(tǒng)調(diào)用這個函數(shù)時,系統(tǒng)會在Activity被異常Destory時傳遞 Bundle 對象,這樣我們就可以增加額外的信息到Bundle中并保存到系統(tǒng)中。若系統(tǒng)在Activity被Destory之后想重新創(chuàng)建這個Activity實例時,之前的Bundle對象會(系統(tǒng))被傳遞到你我們activity的onRestoreInstanceState()方法與 onCreate() 方法中。

basic-lifecycle-savestate

Figure 2. 當系統(tǒng)開始停止Activity時,只有在Activity實例會需要重新創(chuàng)建的情況下才會調(diào)用到onSaveInstanceState() (1) ,在這個方法里面可以指定額外的狀態(tài)數(shù)據(jù)到Bunde中。如果這個Activity被destroyed然后這個實例又需要被重新創(chuàng)建時,系統(tǒng)會傳遞在 (1) 中的狀態(tài)數(shù)據(jù)到 onCreate() (2) 與 onRestoreInstanceState()(3).

(通常來說,跳轉(zhuǎn)到其他的activity或者是點擊Home都會導致當前的activity執(zhí)行onSaveInstanceState,因為這種情況下的activity都是有可能會被destory并且是需要保存狀態(tài)以便后續(xù)恢復使用的,而從跳轉(zhuǎn)的activity點擊back回到前一個activity,那么跳轉(zhuǎn)前的activity是執(zhí)行退棧的操作,所以這種情況下是不會執(zhí)行onSaveInstanceState的,因為這個activity不可能存在需要重建的操作)

保存Activity狀態(tài)

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

為了給Activity保存額外的狀態(tài)信息,你必須實現(xiàn)onSaveInstanceState() 并增加key-value pairs到 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);
}

Caution: 必須要調(diào)用 onSaveInstanceState() 方法的父類實現(xiàn),這樣默認的父類實現(xiàn)才能保存視圖狀態(tài)的信息。

恢復Activity狀態(tài)

當Activity從Destory中重建,我們可以從系統(tǒng)傳遞的Activity的Bundle中恢復保存的狀態(tài)。 onCreate() 與 onRestoreInstanceState() 回調(diào)方法都接收到了同樣的Bundle,里面包含了同樣的實例狀態(tài)信息。

由于 onCreate() 方法會在第一次創(chuàng)建新的Activity實例與重新創(chuàng)建之前被Destory的實例時都被調(diào)用,我們必須在嘗試讀取 Bundle 對象前檢測它是否為null。如果它為null,系統(tǒng)則是創(chuàng)建一個新的Activity實例,而不是恢復之前被Destory的Activity。

下面是一個示例:演示在onCreate方法里面恢復一些數(shù)據(jù):

@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
    }
    ...
}

我們也可以選擇實現(xiàn) onRestoreInstanceState() ,而不是在onCreate方法里面恢復數(shù)據(jù)。 onRestoreInstanceState()方法會在 onStart() 方法之后執(zhí)行. 系統(tǒng)僅僅會在存在需要恢復的狀態(tài)信息時才會調(diào)用 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: 與上面保存一樣,總是需要調(diào)用onRestoreInstanceState()方法的父類實現(xiàn),這樣默認的父類實現(xiàn)才能保存視圖狀態(tài)的信息。更多關于運行時狀態(tài)改變引起的recreate我們的activity。請參考Handling Runtime Changes.


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號