Activity 狀態更改

前言

  • 用戶觸發和系統觸發的不同事件會導致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. 殺死後臺應用

該操作分爲三步,分別進行講解:

  1. 用戶進入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
    
  2. 用戶按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
    
  3. 如果用戶再次進入應用,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
    
  4. 如果用戶殺死該後臺應用,Activity將會可能會經歷onDestroy(),但很有可能不會執行onDestroy()所以儘量不要在onDestroy()中進行資源釋放。

關於第4點進行拓展:
從後臺強殺分兩種情況:

第一種:當前僅有一個activity,這時候,強殺,是會執行onDestroy方法的;

第二種:棧裏面的第一個沒有銷燬的activity會執行ondestroy方法,其他的不會執行。

比如說:從Mainactivity跳轉到activityA(或者繼續從activityA再跳轉到activityB),這時候,從後臺強殺,只會執行MainactivityonDestroy方法,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

代碼

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