關於 Android 手機橫豎屏切換時 Activity 的生命周期問題,網上有很多相似的文章,大多數都是說明在豎屏切換橫屏時 Activity 會重啟一次,而在橫屏切換豎屏時 Activity 會重啟兩次。
我本身不太理解這樣設計的意義,並且覺得新版本會解決這個問題,所以做了一項測試,測試環境為 Android 7.0 模擬器。
測試
測試首先創建一個新的 Activity,並在其各個生命周期方法內打印日志,並執行如下操作得到結果:
在 targetSdkVersion 的值大於 12 時
- Activity啟動
I/System.out: onCreate I/System.out: onStart I/System.out: onResume
- 豎屏切換為橫屏
I/System.out: onConfigurationChanged I/System.out: onPause I/System.out: onSaveInstanceState I/System.out: onStop I/System.out: onDestroy I/System.out: onCreate I/System.out: onStart I/System.out: onRestoreInstanceState I/System.out: onResume
- 橫屏切回豎屏
I/System.out: onConfigurationChanged I/System.out: onPause I/System.out: onSaveInstanceState I/System.out: onStop I/System.out: onDestroy I/System.out: onCreate I/System.out: onStart I/System.out: onRestoreInstanceState I/System.out: onResume
- 配置
android:configChanges="orientation|screenSize"后,豎屏切換為橫屏
I/System.out: onConfigurationChanged
- 配置
android:configChanges="orientation|screenSize"后,橫屏切回豎屏
I/System.out: onConfigurationChanged
在 targetSdkVersion 的值小於或等於 12 時
- Activity啟動
I/System.out: onCreate I/System.out: onStart I/System.out: onResume
- 豎屏切換為橫屏
I/System.out: onConfigurationChanged I/System.out: onPause I/System.out: onSaveInstanceState I/System.out: onStop I/System.out: onDestroy I/System.out: onCreate I/System.out: onStart I/System.out: onRestoreInstanceState I/System.out: onResume
- 橫屏切回豎屏
I/System.out: onConfigurationChanged I/System.out: onPause I/System.out: onSaveInstanceState I/System.out: onStop I/System.out: onDestroy I/System.out: onCreate I/System.out: onStart I/System.out: onRestoreInstanceState I/System.out: onResume
- 配置
android:configChanges="orientation"后,豎屏切換為橫屏
I/System.out: onConfigurationChanged
- 配置
android:configChanges="orientation"后,橫屏切回豎屏
I/System.out: onConfigurationChanged
總結
可以發現新版本 Android 設備上的運行結果和網上的結論並不完全相同,在橫豎屏切換時,都會調用一次 onConfigurationChanged,並重啟 Activity 一次,行為完全一致,具體的生命周期為:
I/System.out: onConfigurationChanged I/System.out: onPause I/System.out: onSaveInstanceState I/System.out: onStop I/System.out: onDestroy I/System.out: onCreate I/System.out: onStart I/System.out: onRestoreInstanceState I/System.out: onResume
在 targetSdkVersion 的值大於 12 時,配置 android:configChanges="orientation|screenSize",
在 targetSdkVersion 的值小於或等於 12 時,配置 android:configChanges="orientation",
可以做到攔截 Activity 的重新創建:
I/System.out: onConfigurationChanged
后續
將會對過去版本的 Android 設備做相應的測試,來驗證得到結果。
改進
通常研究設備旋轉帶來的 Activity 重啟問題,是為了解決 Activity 重啟導致成員變量未保存引發運行出錯。但之所以 Activity 會重啟是因為運行時配置發生了更變,可能有更適合的資源來匹配新的設備配置,例如在橫屏時,有更好利用空間的橫版布局資源,這時就需要 Activity 重新加載布局顯示。
所以,好的解決辦法是利用 onSaveInstanceState(Bundle outState) 方法保存成員變量的值到 Bundle 對象中,在 Activity 重啟后,再在 onCreate(Bundle savedInstanceState) 中獲取這些保存的信息。
