入棧的Activity由於系統資源不足被被回收了怎麼辦

當一個活動進入到了停止狀態,是有可能被系統回收的。那麼想象以下場景

應用中有一個活動 A,用戶在活動 A 的基礎上啓動了活動 B,活動 A 就進入了停止狀態,這個時候由於系統內存不足,將活動 A 回收掉了,然後用戶按下 Back 鍵返回活動 A, 會出現什麼情況呢?其實還是會正常顯示活動 A的, 只不過這時並不會執行 onRestart()方法,而是會執行活動 A 的 onCreate()方法,因爲活動 A 在這種情況下會被重新創建一次。這樣看上去好像一切正常,可是別忽略了一個重要問題,活動 A 中是可能存在臨時數據和狀態的。

打個比方,MainActivity 中有一個文本輸入框,現在你輸入了一段文字,然後啓動 NormalActivity,這時 MainActivity 由於系統內存不足被回收掉,過了一會你又點擊了Back 鍵回到 MainActivity,你會發現剛剛輸入的文字全部都沒了,因爲 MainActivity 被重新創建了。

如果我們的應用出現了這種情況,是會嚴重影響用戶體驗的,所以必須要想想辦法解決這個問題。查閱文檔可以看出,Activity 中還提供了一個 onSaveInstanceState()回調方法,這個方法會保證一定在活動被回收之前調用,因此我們可以通過這個方法來解決活動被回收時臨時數據得不到保存的問題。

onSaveInstanceState()方法會攜帶一個 Bundle 類型的參數,Bundle 提供了一系列的方法用於保存數據,比如可以使用 putString()方法保存字符串,使用 putInt()方法保存整型數據,以此類推。每個保存方法需要傳入兩個參數,第一個參數是鍵,用於後面從 Bundle 中取值,第二個參數是真正要保存的內容。

在 MainActivity 中添加如下代碼就可以將臨時數據進行保存:

@Override

protected void onSaveInstanceState(Bundle outState) {

super.onSaveInstanceState(outState);

  String tempData = "Something you just typed";

  outState.putString("data_key", tempData);

}

數據是已經保存下來了,那麼我們應該在哪裏進行恢復呢?細心的你也許早就發現,我們一直使用的 onCreate()方法其實也有一個 Bundle 類型的參數。這個參數在一般情況下都是null,但是當活動被系統回收之前有通過 onSaveInstanceState()方法來保存數據的話,這個參數就會帶有之前所保存的全部數據,我們只需要再通過相應的取值方法將數據取出即可。

修改 MainActivity 的 onCreate()方法,如下所示:

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

Log.d(TAG, "onCreate");

requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.activity_main);

if (savedInstanceState != null) {

String tempData = savedInstanceState.getString("data_key");

Log.d(TAG, tempData);

}

……

}

取出值之後再做相應的恢復操作就可以了,比如說將文本內容重新賦值到文本輸入框上,這裏我們只是簡單地打印一下。
不知道你有沒有察覺,使用 Bundle 來保存和取出數據是不是有些似曾相識呢?沒錯!我們在使用 Intent 傳遞數據時也是用的類似的方法。這裏跟你提醒一點,Intent 還可以結合Bundle 一起用於傳遞數據的,首先可以把需要傳遞的數據都保存在 Bundle 對象中,然後再將 Bundle 對象存放在 Intent 裏。到了目標活動之後先從 Intent 中取出 Bundle,再從 Bundle
中一一取出數據。

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