Android 異常情況下的生命週期分析
異常情況下的生命週期分析
一:資源相關的系統配置發生改變導致Activity被殺死並重新建立(以旋轉螢幕為例)
樣例程式碼,
首先再onSaveInstanceState
中儲存一個字串,然後當 Activity
被銷燬並重新建立的時後,再去獲取之前儲存的字串。接收的位置可以在 onRestoreInstanceState
或者onCreate
,二者的區別是: onRestoreInstanceState
一旦被呼叫其引數Bundle savedInstanceState
一定是有值的,不需要額外判空;但onCreate
不行,因為onCreate
如果是正常啟動,其引數Bundle savedInstanceState
null
,所以必須進行額外判斷。官方推薦採用 onRestoreInstanceState
進行恢復資料。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState != null){ String test = savedInstanceState.getString("test"); Log.d(TAG, "[onCreate] restore extra_test: " + test); } } @Override protected void onSaveInstanceState(Bundle outState){ super.onSaveInstanceState(outState); Log.d(TAG,"onSaveInstanceState"); outState.putString("test","test"); } @Override protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); String test = savedInstanceState.getString("test"); Log.d(TAG,"[onRestoreInstanceState] restore test: " + test); }
當旋轉屏幕後,執行的日誌如下:
日誌分析
當系統配置發生改變後,Activity 會被銷燬,其onPause、onStop、onDestroy 均會被呼叫,同時由於Activity 是在異常情況下終止的,系統會呼叫 onSaveInstanceState 來儲存當前Activity的狀態。這個方法的呼叫時機是在 onStop 之前,它和 onPause 沒有既定的時序關係,它既可能在onPause之前呼叫,也可能在onPause之後呼叫。(當Android api為28時,onStop會在其之前,即 onSaveInstanceState 出現在 onStop之後,onDestroy之前,與日誌情況相符
onSaveInstanceState呼叫時機
- 當用戶按下HOME鍵時。 這是顯而易見的,系統不知道你按下HOME後要執行多少其他的程式,自然也不知道activity A是否會被銷燬,故系統會呼叫onSaveInstanceState,讓使用者有機會儲存某些非永久性的資料。以下幾種情況的分析都遵循該原則
- 長按HOME鍵,選擇執行其他的程式時
- 按下電源按鍵(關閉螢幕顯示)時
- 從activity A中啟動一個新的activity時
- 螢幕方向切換時,例如從豎屏切換到橫屏時。
onSaveInstanceState
的呼叫遵循一個重要原則,即當系統“未經你許可”時銷燬了你的activity
,則onSaveInstanceState
會被系統呼叫,這是系統的責任,因為它必須要提供一個機會讓你儲存你的資料(當然你不儲存那就隨便你了)
避免當系統配置發生改變後,Activity被重新建立
給configChanges
屬性新增值
例如解決旋轉螢幕的重新建立:android:configChanges="orientation|screenSize"
主要使用的幾個值
- keyboardHidden : 鍵盤的可訪問性發生了改變,例如調出了鍵盤
- orientation : 螢幕方向發生了改變,例如旋轉了螢幕
- screenSize : 當螢幕的尺寸資訊發省了改變,當旋轉螢幕時,螢幕尺寸會發生改變,但這個選項比較特殊和編譯選項有關,當編譯選項中的 minSdkVersion 和 targetSdkVersion 均低於13時,此選項不會導致 Activity 重啟,否則會導致 Activity 重啟(API 13 新新增)
- locale : 裝置的本地位置發生了改變,一般指切換了系統語言
二:資源記憶體不足情況導致低優先順序的Activity被殺死
這種情況我們不好模擬,但是其資料儲存和恢復過程和情況一完全一致。這裡我們描述一下Activity的優先順序情況。Activity 按照優先順序從高到低,可以分為如下三種:
-
前臺Activity-- 正在和使用者互動的Activity, 優先順序最高。
-
可見但非前臺Activity——比如 Activity中彈出了一個對話方塊,導致Activity可見,但是位於後臺無法和使用者直接互動。
-
後臺Activity--已經 被暫停的Activity,比如執行了onStop, 優先順序最低。
當系統記憶體不足時,系統就會按照上述優先順序去殺死目標 Activity 所在的程序,並在後續通過 onSaveInstanceState 和 onRestoreInstanceState 來儲存和恢復數資料。如果一個程序中沒有四大元件在執行,那麼這個程序將很快被系統殺死,因此,一些後臺工作不適合脫離四大元件而獨自執行在後臺中,這樣程序很容易被殺死。比較好的方法是將後臺工作放入Service中從而保證程序有一定的優先順序,這樣就不會輕易地被系統殺死。