Activity 生命週期詳解與異常情況生命週期

博主聲明:

轉載請在開頭附加本文鏈接及作者信息,並標記爲轉載。本文由博主 威威喵 原創,請多支持與指教。

本文首發於此   博主威威喵  |  博客主頁https://blog.csdn.net/smile_running

    在學習 Android 時候,通常一開始學習的都是它的生命週期,誰讓我們第一個創建的就是 MainActivity 類呢。學習 Activity 就要從它的生命週期入手,這是我們瞭解它最快的一種方式,瞭解它的生命週期,大概就可以知道它的工作時間。比如,我們創建應該 MainActivity 就要重寫它的 onCreate 方法,在 onCreate 中通過 setContentView 設置佈局文件才能夠真正的感受到 Activity 的存在,如果沒有 setContentView 就是灰白灰白的,空空如也。

    這次呢。我們先不去管它 setContentView 幹了哪些事情,先來把 Activity 的幾種生命週期及情境搞明白。百度偷了一張圖過來,自己懶得畫了,將就看吧:

     這張圖,從上到下羅列了 Activity 的幾種生命週期,它的幾種生命週期分爲四中狀態,如下圖:

下面是一些概念性的描述,蠻看吧,反正也記不住!

onCreate : 該方法是在Activity被創建時回調,它是生命週期第一個調用的方法,我們在創建Activity時一般都需要重寫該方法,然後在該方法中做一些初始化的操作,如通過setContentView設置界面佈局的資源,初始化所需要的組件信息等。 


onStart : 此方法被回調時表示Activity正在啓動,此時Activity已處於可見狀態,只是還沒有在前臺顯示,因此無法與用戶進行交互。可以簡單理解爲Activity已顯示而我們無法看見擺了。 


onResume : 當此方法回調時,則說明Activity已在前臺可見,可與用戶交互了(處於前面所說的Active/Running形態),onResume方法與onStart的相同點是兩者都表示Activity可見,只不過onStart回調時Activity還是後臺無法與用戶交互,而onResume則已顯示在前臺,可與用戶交互。當然從流程圖,我們也可以看出當Activity停止後(onPause方法和onStop方法被調用),重新回到前臺時也會調用onResume方法,因此我們也可以在onResume方法中初始化一些資源,比如重新初始化在onPause或者onStop方法中釋放的資源。 


onPause : 此方法被回調時則表示Activity正在停止(Paused形態),一般情況下onStop方法會緊接着被回調。但通過流程圖我們還可以看到一種情況是onPause方法執行後直接執行了onResume方法,這屬於比較極端的現象了,這可能是用戶操作使當前Activity退居後臺後又迅速地再回到到當前的Activity,此時onResume方法就會被回調。當然,在onPause方法中我們可以做一些數據存儲或者動畫停止或者資源回收的操作,但是不能太耗時,因爲這可能會影響到新的Activity的顯示——onPause方法執行完成後,新Activity的onResume方法纔會被執行。 


onStop : 一般在onPause方法執行完成直接執行,表示Activity即將停止或者完全被覆蓋(Stopped形態),此時Activity不可見,僅在後臺運行。同樣地,在onStop方法可以做一些資源釋放的操作(不能太耗時)。 


onRestart :表示Activity正在重新啓動,當Activity由不可見變爲可見狀態時,該方法被回調。這種情況一般是用戶打開了一個新的Activity時,當前的Activity就會被暫停(onPause和onStop被執行了),接着又回到當前Activity頁面時,onRestart方法就會被回調。 


onDestroy :此時Activity正在被銷燬,也是生命週期最後一個執行的方法,一般我們可以在此方法中做一些回收工作和最終的資源釋放。 

其實,說白了就對應幾種狀態(創建和銷燬狀態、可見與不可見狀態、是不是可操作狀態),如下圖:

     每一種生命週期都兩兩相對,除了 onRestart 比較特殊,單身狗,被孤立了。反正,這樣看是很難記住的,太過於概念化的東西容易忘記,必須手動操作一波,記得更牢固。

    來吧,實際操作一下。書本上的老套路,一個 MainActivity,一個 SecondActivity,也許有人會覺得能比書上詳細嗎?這我不敢說,但是我看的基本入門書,好多都沒講到,也就是介紹一下生命週期而已,一些情境都沒涉及到,如果你看下去,就會知道有哪些區別了。

    首先,我們啓動一個 Activity 時,第一個啓動的是 Application,毫無疑問,Application 的生命週期是最長的,也就是你點開那個桌面小圖標時,它就已經啓動了。於此同時,Application 就會尋找它下面一級帶有 LAUNCHER 的過濾器,然後啓動的就是這個 Activity,參考下面的 manifest 代碼:

    <application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        tools:ignore="AllowBackup,GoogleAppIndexingWarning">
        
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SecondActivity" />
        
    </application>

    這裏就解釋了,Activity 並不是平白無故的啓動,只有在清單文件中註冊過的才能啓動,當然,一個程序是可以不用任何 Activity 的。

    Application 的啓動,通常就只有 onCreate 是它的生命週期,在低內存下還會執行其他的方法。Application onCreate 之後,就輪到 MainActivity 的 onCreate,下面來看這一段截圖:

 1、當一個 Activity 啓動完成時,它的生命週期如上圖所示

 onCreate -> onStart 從不可見 到 可見 -> onResume 從不可交互 到 可交互。

2、點擊 helloword 啓動了 SecondActivity ,生命週期的變化如下:

     MainActivity 沒有執行 finish() 方法, 變成了 onStop 停止狀態,意味着不可見,不可交互。啓動 SecondActivity 生命週期是一樣,不再說了。 

3、當點擊 back 時,生命週期變化如下:

    首先,它執行的是 SecondActivity 的 onBackPressed 的方法返回。可以看到,MainActivity 在前面執行到 onStop,當按下 back 時,它執行的是 onRestart -> onStart -> onResume

    而 SecondActivity 執行了 onStop -> onDestroy ,表示由停止狀態 被 摧毀了。

4、當在 MainActivity 裏面執行了 finish() 方法,將 MainActivity 關閉了,又會怎麼樣呢?

 可以看到,MainActivity finish 後,不僅執行了 onStop,還執行了 onDestroy,徹底的把 MainActivity 給摧毀了。

5、MainActivity 被摧毀了,這時再按 back 會怎麼樣呢?

 顯然 MainActivity 已經沒了,兩個 Activity 都被摧毀了,最後也只能回到桌面上了。

6、這個時候,再此點擊桌面圖片,會再次創建 Application 嗎?

 答案是不會的,因爲我們的 Application 並沒有被殺死,所以這裏的 App 的 onCreate 就不會再執行了。

7、那如何保證徹底退出應用程序呢,保證殺死 app 呢?

我們通過 SecondActivity 的 onBackPressed() 方法內加入: System.exit(0) ,表示殺死當前應用,徹底退出程序,看看效果:

 點擊 back,再次點擊桌面圖片,發現 App 的 onCreate 執行了,表明我們剛剛成功的殺死這個進程了。

8、切換任務管理快捷鍵時,生命週期會有什麼變化?

9、按下 home 有什麼變化呢?

 原來是這樣的,是不是發現了什麼規律呢?

如果沒有執行 finish,那麼 Activity 就不會 onDestroy,而按下 back 時,相當於 finish 了,必定執行 onDestroy

當按下 home 和 任務管理 時,這時 Activity 處於不可見狀態,但又沒有被 finish,所以它只會到 onStop,然後等待被 onReStart,如果這個期間被結束任務了,那它會執行 onDestroy 嗎?

 答案是不會的,看上面一個圖,從任務裏面殺死了 app,並不會執行 onDestroy。

    WTF,寫到最後,才發現我前面漏掉了一個 onPause 生命週期方法。由於圖太多了,懶得重新弄了。onPause 是會在 onStop 之前執行的,如果 onStop 執行了,那麼必定會執行 onPause,自己試一試吧,多的不說了。Activity 息息相關的也就這幾種場景的生命週期,屬於正常的生命週期。

    還有就是 System.exit(0) 強行把 app 殺死了,這樣的話,就會導致 onPause、onStop 、onDestroy 等生命週期沒辦法執行,如果要保存 Activity 一些數據的話,這樣沒法從  onPause、onStop 、onDestroy 中獲取數據。

    System.exit(0)也是會有問題的,比如在開啓 SecondActivity 時,沒有把 MainActivity 給 finish 調,這時它又會啓動一個新的 MainActivity ,比如出現這樣的情況:

 這中情況發生的概率也很高,如果對 System.exit(0) 不瞭解的話,就會出現問題。解決的方式就是最好新建一個管理所以 Activity 的工具類,在真正需要退出 app 的地方,把 Activity 全部都 finish 掉,然後再 System.exit(0) 就不會有問題了。

還有一種是 ANR 的情況發生,如果等待能完成到還好,如果完成不了,那麼這種情況下也不會執行 onPause、onStop 、onDestroy,比如用戶在輸入完成後提交發生了 ANR,那麼這些剛剛填的信息應該如何保證能夠保存呢?

 當然,我們可以通過監聽控件的事件來保存,這是一種辦法。

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