很多人依賴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);
}
參考
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