前言
-
用戶觸發和系統觸發的不同事件會導致
Activity
從一個狀態轉換到另一個狀態。本文主要介紹發上此類轉換的一些常見情況,以及如何處理這些轉換。 -
在交接本文之前需要知道
Activity
狀態的情況,可以查看上一篇文章 《Activity生命週期》
1. 配置發生了更改
有很多事件會觸發配置更改。最顯著的例子就是橫豎屏之間的切換。其他情況,如語言或輸入設備的改變等,也可能導致配置更改。
當配置發生更改時,Activity
會銷燬並重新創建。原始Activity
實例將觸發onPause()
、onStop()
、onSaveInstanceState()
、onDestroy()
回調。系統將創建新的Activity
實例,並觸發onCreate()
、onStart()
、onRestoreInstanceState()
、onResume()
回調。
- 進入Activity:
2020-06-01 16:12:11.218 6286-6286/com.xyz.activity E/xx: the Activity of 144510544 is created 2020-06-01 16:12:11.218 6286-6286/com.xyz.activity E/xx: onCreate 2020-06-01 16:12:11.220 6286-6286/com.xyz.activity E/xx: onStart 2020-06-01 16:12:11.220 6286-6286/com.xyz.activity E/xx: onResume
- 旋轉屏幕:
2020-06-01 16:13:52.591 6286-6286/com.xyz.activity E/xx: onPause 2020-06-01 16:13:52.592 6286-6286/com.xyz.activity E/xx: onStop 2020-06-01 16:13:52.592 6286-6286/com.xyz.activity E/xx: onSaveInstanceState 2020-06-01 16:13:52.592 6286-6286/com.xyz.activity E/xx: onDestroy 2020-06-01 16:13:52.593 6286-6286/com.xyz.activity E/xx: the Activity of 144510544 is finished 2020-06-01 16:13:52.618 6286-6286/com.xyz.activity E/xx: the Activity of 29845855 is created 2020-06-01 16:13:52.618 6286-6286/com.xyz.activity E/xx: onCreate 2020-06-01 16:13:52.620 6286-6286/com.xyz.activity E/xx: onStart 2020-06-01 16:13:52.622 6286-6286/com.xyz.activity E/xx: onRestoreInstanceState 2020-06-01 16:13:52.622 6286-6286/com.xyz.activity E/xx: key get :hello world! 2020-06-01 16:13:52.623 6286-6286/com.xyz.activity E/xx: onResume
拓展 : 如何防止旋轉屏幕導致Activity重新創建
- 方法1:禁止旋轉屏幕(簡單直接,對於沒有旋轉屏幕需求的app可使用)
<activity android:name=".MyActivity" android:screenOrientation="portrait" />
- 方法2:修改
AndroidManifest.xml
配置
在activity屬性中加入:<activity android:name=".ConfigChangeActivity" android:configChanges="orientation|screenSize" />
android:configChanges
:這個方法主要是負責列出清單,當清單上用戶指定的設置改變時,Activity會自己處理這些變化。
orientation
:屏幕界面旋轉(可能是用戶手動旋轉的),【注意:如果你的開發API等級等於或高於13,你還需要設置screenSize
,因爲screenSize會在屏幕旋轉時改變】
2. Activity 或對話框顯示在前臺
如果有新的 Activity
或對話框出現在前臺,並且局部覆蓋了正在進行的 Activity
,則被覆蓋的 Activity
會失去焦點並進入“已暫停”狀態。然後,系統會調用onPause()
。
當被覆蓋的 Activity
返回到前臺並重新獲得焦點時,會調用onResume()
。
如果有新的 Activity
或對話框出現在前臺,奪取了焦點且完全覆蓋了正在進行的 Activity
,則被覆蓋的Activity
會失去焦點並進入“Stoped”狀態。然後,系統會快速地接連調用onPause()
和onStop()
。
當被覆蓋的 Activity
的同一實例返回到前臺時,系統會對該 Activity
調用 onRestart()
、onStart()
和onResume()
。如果被覆蓋的 Activity 的新實例進入後臺,則系統不會調用 onRestart()
,而只會調用 onStart()
和onResume()
。
3. 用戶點按“返回”按鈕
如果Activity
位於前臺,並且用戶點按了返回按鈕,Activity
將依次經歷 onPause()
、onStop()
、 onDestroy()
回調。活動不僅會被銷燬,還會從返回堆棧中移除。
需要注意的是,在這種情況下,默認不會觸發onSaveInstanceState()
回調。此行爲基於的假設是,用戶點按返回按鈕時不期望返回 Activity
的同一實例。不過,您可以通過替換onBackPressed()
方法實現某種自定義行爲,例如“confirm-quit”對話框。
如果您替換 onBackPressed()
方法, 建議被替換的方法調用 super.onBackPressed()。否則,返回按鈕的行爲可能會讓用戶感覺突兀。
4. 殺死後臺應用
該操作分爲三步,分別進行講解:
- 用戶進入Activity,Activity將依次經歷
onCreate()
、onStart()
、onResume()
回調。2020-06-01 19:32:39.666 5840-5840/com.xyz.activity E/xx: the Activity of 4362927 is created 2020-06-01 19:32:39.666 5840-5840/com.xyz.activity E/xx: onCreate 2020-06-01 19:32:39.668 5840-5840/com.xyz.activity E/xx: onStart 2020-06-01 19:32:39.668 5840-5840/com.xyz.activity E/xx: onResume
- 用戶按Home鍵,使應用退到後臺,
Activity
將依次經歷onPause()
、onStop()
、onSaveInstanceState()
回調。2020-06-01 19:37:32.071 6168-6168/com.xyz.activity E/xx: onPause 2020-06-01 19:37:32.104 6168-6168/com.xyz.activity E/xx: onStop 2020-06-01 19:37:32.104 6168-6168/com.xyz.activity E/xx: onSaveInstanceState
- 如果用戶再次進入應用,
Activity
將會依次經歷onRestart()、onStart()、onResume()回調。2020-06-01 19:40:08.292 6168-6168/com.xyz.activity E/xx: onRestart 2020-06-01 19:40:08.295 6168-6168/com.xyz.activity E/xx: onStart 2020-06-01 19:40:08.296 6168-6168/com.xyz.activity E/xx: onResume
- 如果用戶殺死該後臺應用,Activity將會可能會經歷
onDestroy()
,但很有可能不會執行onDestroy()
所以儘量不要在onDestroy()
中進行資源釋放。
關於第4點進行拓展:
從後臺強殺分兩種情況:
第一種:當前僅有一個activity,這時候,強殺,是會執行onDestroy方法的;
第二種:棧裏面的第一個沒有銷燬的activity會執行ondestroy方法,其他的不會執行。
比如說:從Mainactivity
跳轉到activityA
(或者繼續從activityA
再跳轉到activityB
),這時候,從後臺強殺,只會執行Mainactivity
的onDestroy
方法,ActivityA
(以及activityB
)的onDestroy
方法都不會執行;(原文)
試了一下 該分析也不一定有效:
2020-06-01 20:05:55.912 10129-10129/com.xyz.activity E/xx: the Activity of 256450186 is created
2020-06-01 20:05:55.912 10129-10129/com.xyz.activity E/xx: MainActivity onCreate
2020-06-01 20:05:55.920 10129-10129/com.xyz.activity E/xx: MainActivity onStart
2020-06-01 20:05:55.921 10129-10129/com.xyz.activity E/xx: MainActivity onResume
2020-06-01 20:05:58.622 10129-10129/com.xyz.activity E/xx: MainActivity onPause
2020-06-01 20:05:58.636 10129-10129/com.xyz.activity E/xx: the Activity of 244799732 is created
2020-06-01 20:05:58.636 10129-10129/com.xyz.activity E/xx: NormalActivity onCreate
2020-06-01 20:05:58.638 10129-10129/com.xyz.activity E/xx: NormalActivity onStart
2020-06-01 20:05:58.639 10129-10129/com.xyz.activity E/xx: NormalActivity onResume
2020-06-01 20:05:59.088 10129-10129/com.xyz.activity E/xx: MainActivity onStop
2020-06-01 20:05:59.088 10129-10129/com.xyz.activity E/xx: MainActivity onSaveInstanceState
2020-06-01 20:06:01.008 10129-10129/com.xyz.activity E/xx: NormalActivity onPause
2020-06-01 20:06:01.042 10129-10129/com.xyz.activity E/xx: NormalActivity onStop
2020-06-01 20:06:01.042 10129-10129/com.xyz.activity E/xx: NormalActivity onSaveInstanceState
2020-06-01 20:06:01.665 10129-10129/com.xyz.activity E/xx: MainActivity onDestroy
2020-06-01 20:06:01.666 10129-10129/com.xyz.activity E/xx: the Activity of 256450186 is finished
2020-06-01 20:06:01.673 10129-10129/com.xyz.activity E/xx: NormalActivity onDestroy
2020-06-01 20:06:01.674 10129-10129/com.xyz.activity E/xx: the Activity of 244799732 is finished