不要太依賴Activity的生命週期, 不要依賴Activity變量,不主動保存恢復數據會發生意外。

很多人依賴Activity的生命週期來處理程序。這裏面有很多坑需要大家注意。關於onSaveInstanceState,你需要知道這些知識  。

1.startActivity或startActivityForResult時,把數據保存在activity變量裏。onActivityResult之後再把保存在activity變量裏的數據拿來直接用。

一般情況下是沒有問題的。從點下一個按鈕startActivityForResult開始,到onActivityResult ,這之間週期如下面所示

D/LifeCycleTest(22601): onSaveInstanceState
D/LifeCycleTest(22601): onPause
D/LifeCycleTest(22601): onStop

其他Activity顯示中......

D/LifeCycleTest(22601): onActivityResult -1
D/LifeCycleTest(22601): onRestart
D/LifeCycleTest(22601): onStart
D/LifeCycleTest(22601): onResume

可以看到,其他Activity顯示之前,最後調用的是onStop.
從其他Activity轉回來,最先實行的是onActivityResult。

 

2.還有一種情況是startActivityForResult調用的Activity在前面,Activity不完全消失,在背後還可以見的情況。週期如下所示。

D/LifeCycleTest(22601): onSaveInstanceState
D/LifeCycleTest(22601): onPause

D/LifeCycleTest(22601): onActivityResult -1
D/LifeCycleTest(22601): onResume

可以看見onStop,onRestart,onStart都不會被執行。

 

3.還有一種情況要認識到
onPause()之後的activity  不會系統kill掉(HONEYCOMB(android3.0)之前,可能kill)
onStop() 之後的activity,可能會被系統kill掉(橫屏豎屏轉換時,startActivity之後系統資源不夠時)
被系統kill掉,activity的變量變量保存的數據就有可能會丟失。
所以如果你的onActivityResult處理依賴activity的變量的話,就有可能會異常了。
所以我們還是需要在onSaveInstanceState()裏,做一下保存數據的處理。
在onSaveInstanceState保存的Bundle,在onCreate 或者onRestoreInstanceState裏可以取得。

onSaveInstanceState的調用時機:
android3.0之前:onResume() -- [optional]onSaveInstanceState() -- onPause()
android3.0之後:onResume() -- onPause() -- [optional]onSaveInstanceState() -- onStop()

驗證
 

驗證一下(利用activity自動旋轉會保存之前狀態,並重新恢復的特點):

android2.3

android5.0


4.在activity的一個生命週期中,onSaveInstanceState()並非一定調用:
如果activity不是被系統kill掉,而是你自己的調用finish()的話,onSaveInstanceState()是不會執行的。
主動調用finish(),onPause()、onStop()仍然會執行,但onSaveInstanceState()不執行。

驗證

HomeActivity啓動ActivityB,不finish自己:

HomeActivity啓動ActivityB,finish自己:

 

5.onCreate(),onRestoreInstanceState()都收到Bundle包含實例狀態信息,我們在那個時機取得比較好?
onCreate()和onRestoreInstanceState()的區別時,onCreate()一定會執行,但onRestoreInstanceState()不一定會執行。
onRestoreInstanceState只有在activity被系統回收,重新創建activity的情況下才會被調用。

調用的例子:
屏幕旋轉橫豎屏切換時:
onPause -> onSaveInstanceState -> onStop -> onDestroy -> onCreate -> onStart -> onRestoreInstanceState -> onResume
在這裏onRestoreInstanceState被調用,是因爲屏幕切換時原來的activity被系統回收了,又重新創建了一個新的activity。

不會被調用的例子:
而按HOME鍵返回桌面,又馬上點擊應用圖標回到原來頁面時,activity生命週期如下:
onPause -> onSaveInstanceState -> onStop -> onRestart -> onStart -> onResume
因爲activity沒有被系統回收,因此onRestoreInstanceState沒有被調用。

如果onRestoreInstanceState被調用了,則頁面必然被回收過,則onSaveInstanceState必然被調用過。

在onCreate()恢復狀態數據的話一定要檢查是否爲空:

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

onRestoreInstanceState()只有在存在保存狀態的情況下才會恢復,因此您不需要檢查是否Bundle爲空:

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

 

 

Android Fundamentals · LateralView/android-base-project Wiki · GitHub

 

 

參考 
https://araramistudio.jimdo.com/2018/01/18/android%E3%81%AEactivity%E3%81%AF%E5%86%8D%E4%BD%9C%E6%88%90%E3%81%AB%E5%82%99%E3%81%88%E3%81%A6savedinstancestate%E3%82%92%E4%BD%BF%E3%81%8A%E3%81%86/

https://kokufu.blogspot.com/2012/09/onactivityresult.html
https://blog.csdn.net/Rflyee/article/details/50949683

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