1. 程式人生 > >儲存Activity被系統回收前的狀態

儲存Activity被系統回收前的狀態

Activity被銷燬的兩中情況

Activity被銷燬的情況大致可分為兩種。

一是正常行為。如當用戶按了手機的back鍵或者activity呼叫自己的finish()方法而被銷燬。

另一種是非正常行為。如activity處於stop狀態而且長期沒有被使用,或者是前臺的activitiy需要更多的資源因此係統必須關閉後臺程序以回收記憶體。

Activity狀態能儲存的情況

activity由於使用者按下back鍵或activity呼叫finish()方法結束本身而被銷燬,則該activity例項將永遠消失因為它的行為表明該activity不再需要了。

如果activity被銷燬是因為系統強制關閉而不是程式正常的退出行為,那麼即使是

acitivy的例項銷燬了,但是系統仍然記得它的存在。當用戶返回到該activity的時候,系統會使用它被銷燬時候儲存的資料來創建出一個新的activity例項。這些被系統用來恢復之前狀態的資料被稱為“instance state”,是一個存在Bundle物件中的鍵值對集合。

注意:

使用者每次旋轉螢幕,都會引起activity的銷燬和重建。

當改變螢幕的方向時,由於螢幕的配置資訊發生改變,系統會銷燬和重新建立前臺activity。使用者可以在清單檔案中配置activityconfigchange屬性。

資訊儲存在哪

預設情況下,系統會使用Bundle物件去儲存activity佈局中的每個

view物件的資訊(如剛輸入在activity中的文字值)。所以當activity被銷燬和重建,佈局的狀態會自動恢復到之前的狀態。但是如果你的activity需要恢復更多的資訊,比如成員變數資訊,則需要自己動手寫了。

儲存activity的狀態

activity的生命週期中有一個額外的回撥方法onSaveInstanceState(),當用戶離開activity的時候,系統就會呼叫該方法。當系統呼叫這個方法時,會傳遞一個Bunddle物件儲存額外的資訊由於該activity是意外銷燬。

如果activity被銷燬後需重建這個activity例項時,它會傳遞同一個Bundle objectonRestoreInstanceState()

onCreate() 方法中去。如下圖:

 

 當系統停止activity時,它會呼叫onSaveInstanceState()(過程1),如果activity被銷燬了,但是需要建立同樣的例項,系統會把過程1中的狀態資料傳給onCreate()onRestoreInstanceState()(圖中標出的23)。

儲存Activity 

當系統停止activity時,系統會呼叫onSaveInstanceState(),狀態資訊會以鍵值對的形式儲存下來。該方法預設的實現中儲存了activityview的狀態,比如edittext中的文字和listview滾動條的位置等。如果要儲存額外的資訊,必須自己實現onSaveInstanceState()並將資訊以鍵值對形式儲存到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);
}

恢復activity的狀態

activity重建時,需要根據Bundle中的狀態資訊資料恢復activityonCreate() onRestoreInstanceState()回撥函式都會接收到這個Bundle

因為每次建立新的activity例項的或重建一個例項的時候都會呼叫onCreate()方法,所以必須先檢查是否Bundlenull,如果是null,則表明是要建立一個全新的物件,而不是重建一個上次被銷燬的物件。

比如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
    }    
}

除了在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);
}