第一章 Activity的生命週期和啓動模式

1.1 Activity的生命週期全面分析

典型情況下的生命週期:是指在有用戶參與的情況下,Activity所經過的生命週期的改變;
異常情況下的生命週期:指Activity被系統回收或者由於當前設備的configuration(配置)發生改變導致Activity被銷燬重建,異常情況下的生命週期和典型情況下的生命週期略有不同。

1.1.1 典型情況下的生命週期分析

Activity完整的生命週期:

onCreate -> onStart -> onResume -> onPause -> onStop -> onDestroy

onStart ():表示 Activity 已經是可見狀態,但是還沒有出現在前臺,無法和用戶進行交互。但是可以理解爲 Activity 已經顯示出來了,只是我們還看不到。DecorView 還沒有被 WindowMannager 添加。
onResume():此時的 Activity 也是可見狀態,出現在前臺並且可以可用戶交互,而 start() 的時候 Activity 還是在後臺。
onPause():表示 Activity 正在停止,此時可以做一些存儲數據、停止動畫等操作,但是不能耗時,因爲有新的Activity展示在前臺的時候,onPause() 必須先執行完,新 Activity 的 onResume() 才能執行。切換到新的 Activity 的時候,onPause -> onStop;但是如果新的 Activity 是透明主題,那麼當前 Activity 不會執行 onStop。
onStop():表示 Activity 即將停止,可以做一些稍微重量級別的回收工作,但是同樣不能太耗時。
onDestroy(): 表示 Activity 即將被銷燬,可以做一些回收和最終的資源釋放。


問題1:onStart 和 onResume、onPause 和 onStop 從描述上都差不多,對我們來說有什麼實質性的不同呢?
實際使用上其實是差不多的,但是兩個配對的回調代表着不同的意義。onStart 和 onStop 是從 Activity 是否可見這個角度來回調的,onResume 和 onPause 是從 Activity 是否位於前臺這個角度來回調的,除了這個區別,在實際使用中沒有其它明顯區別。
問題2:假設當前 Activity 爲 A,如果這時用戶打開一個新 Activity B,那麼 B 的 onResume 和 A 的 onpause 哪個先執行呢?
官方文檔:不能在 onPause 中做重量級操作,因爲必須 onPause 執行完成以後新 Activity 才能 Resume。

1.1.2 異常情況下的生命週期分析

1:資源相關的系統配置發生改變導致 Activity 被殺死並重新創建
當系統配置(比如旋轉屏幕)發生改變,Activity 會被銷燬。由於 Activity 是在異常情況下終止的,系統調用 onSaveInstanceState(),該方法在 onStop 之前調用。當 Activity 被重新創建後,系統會調用 onRestoreInstanceState(),並且把 Activity 銷燬時 onSaveInstanceState() 方法所保存的 Bundle 對象作爲參數同時傳遞給 onRestoreInstanceState() 和 onCreate(), onRestoreInstanceState() 在onStart() 方法執行時候執行。
保存和恢復 View 層次結構,系統的工作流程:首先 Activity 被意外終止了,Activity 會調用 onSaveInstanceState() 去保存數據,然後委託 Window 保存數據,接着 Window 委託它上面的頂層容器保存數據,一般是指 DecorView ,最後頂層容器會一一通知子元素保存數據,每個子元素也有 onSaveInstanceState() 和 onRestoreInstanceState() 。這種典型的委託思想,類似:View的繪製過程、事件分發。
onRestoreInstanceState() 和 onCreate() 區別:
onRestoreInstanceState() 一旦被調用,一定是有值的,不用額外判斷是否爲空,但是 onCreate() 如果是正常啓動的話,參數 Bundle savedInstanceState 爲空,所以必須要進行判斷。
系統只在 Activity 異常終止的時候纔會調用 onSaveInstanceState() 和 onRestoreInstanceState() 來保存和恢復數據,其它情況下會觸發這個過程。但是按 Home 鍵或者啓動新 Activity 仍然會單獨觸發 onSaveInstanceState()的調用,但是再次回到該 Activity 的時候不會調用 onRestoreInstanceState(),調用 onStart() 。
2:資源內存不足導致低優先級的 Activity 被殺死
Activity 按照優先級從高到低:
(1):前臺 Activity —— 正在和用戶交互的 Activity,優先級最高
(2):可見但非前臺 Activity —— 比如 Activity 中彈出了一個對話框,導致 Activity 可見但是位於後臺無法和用戶直接交互。
(3):後臺 Activity —— 已經被暫停的 Activity,比如執行了 onStop,優先級最低。
當系統內存不足時,系統就會按照上述優先級殺死目標 Activity 所在的進程,並在後續通過 onSaveInstanceState() 和 onRestoreInstanceState() 來存儲和恢復數據。如果一個進程中沒有四大進程在執行,那麼這個進程將很容易被系統殺死。因此,一些後臺工作不適合脫離四大組件而獨立運行在後臺中,這樣進程很容易被殺死。比較好的方法是將後臺工作放入 Service 中保證進程有一定的優先級,這樣就不會輕易地被系統殺死。
當系統配置發生改變後,Activity 會被重新創建,可以給 Activity 指定 configChanges 屬性。

1.2 Activity 的啓動模式

1. Activity 的 LaunchMode

(1) standard:標準模式
系統的默認模式,當用 ApplicationContext 去啓動 standard 模式的 Activity會報錯,因爲 standard 模式的 Activity 默認會進入啓動它的 Activity 所在的棧,但是非 Activity 類型的 Context 並沒有所謂的任務棧。解決此問題的方法是爲待啓動的 Activity 指定 FLAG_ACTIVITY_NEW_TASK 標記位(在 intent 中設置),這樣啓動的時候就會爲它創建一個新的任務棧。此時待啓動 Activity 實際以 singleTask 模式啓動的。
(2) singleTop:棧頂複用模式
如果新 Activity 已經在棧頂,則此 Activity 不會被創建,不會走 Activity 的onCreate() 和 onStart() 方法, onNewIntent() 方法被調用;如果新 Activity 的實例已經存在但是不在棧頂,那麼新 Activity 仍然會被重建。
(3) singleTask:棧內複用模式
這是一種單實例模式,當一個具有 singleTask 模式的 Activity 請求啓動後,比如 Activity A,系統首先會尋找是否存在 A 想要的棧,如果不存在,就創建一個任務棧,然後創建 A 的實例後把 A 放到棧中。如果存在 A 所需的任務棧,這時要看棧中是否有實存在,如果有實例存在,那麼系統就會把該實例之上的 Activity 實例出棧,並調用 Activity 的 onNewIntent,如果實例不存在,就創建 A 的實例並把 A 放入棧中。
(4) singleInstance:單實例模式
具有 singleTask 的所有特性,這種模式的 Activity 只能單獨地位於一個任務棧中。

2. TaskAffinity 和 allowTaskReparenting

TaskAffinity 標識了一個 Activity 所需要的任務棧的名字,默認情況,所有 Activity 的任務棧名字爲應用的包名,單獨指定該參數值的時候,不能與包名相同。該屬性主要和 singleTask 和 allowTaskReparenting 配對使用,其他情況下沒有意義。
TaskAffinity 和 singleTask 配對使用的時候,待啓動的 Activity 會運行在名字和 TaskAffinity 值相同的任務棧中。
TaskAffinity 和 allowTaskReparenting 配對使用的時候,當一個應用 A 啓動應用 B 的某個 allowTaskReparenting 屬性爲 true 的 Activity,那麼當應用 B 再啓動的時候,在 A 中啓動的 B 的 Activity 會從應用 A 的任務棧轉移到應用 B 的任務棧中。
給 Activity 指定啓動模式有兩種,第一種是在 AndroidManifest.xml 中指定,另一種通過在 Intent 實例中設置標記位。 區別:1. 限定範圍有所不同。2. 第二種的優先級較第一種更高。

3. Activity 的 Flags

常用標記位:
Intent.FLAG_ACTIVITY_NEW_TASK:和給 Activity 指定 singleTask 啓動模式效果一樣。
Intent.FLAG_ACTIVITY_SINGLE_TOP:和 singleTop 效果相同。
Intent.FLAG_ACTIVITY_CLEAR_TOP: 具有此標記位的 Activity,當它啓動時,在同一個任務棧中所有位於它上面的 Activity 都要出棧。通常和 singleTask 一塊出現,這種情況下,被啓動的 Activity 實例如果已經存在,系統會調用它的 onNewIntent。如果被啓動的 Activity 採用 standard 模式啓動,那麼它連同它之上的 Activity 都要出棧,系統會創建新的 Activity 實例並放入棧中。
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS: 具有該標記的 Activity 不會出現在歷史 Activity 列表中,某些情況下,我們不想用戶通過歷史列表回到我們的 Activity 的時候這個標記比較有用。等同於在配置文件中指定 Activity 的屬性android:excludeFromRecents="true"

1.3 IntentFilter 的匹配規則

IntentFilter 的過濾信息有 action、category、data。只有一個 Intent 同時匹配 action類別、category 類別、data 類別纔算完全匹配,只有完全匹配才能成功啓動 Activity。一個 Activity 可以有多個 intent-filter,一個 Activity 只要能匹配其中一組就可以成功啓動對應的 Activity。
1. action 的匹配規則
匹配必須字符串完全相同,並區分大小寫。一個過濾規則中可以有多個 action,Intent 中的 action 必須存在且能和過濾規則中的任何一個 action 匹配成功即可。
2. category 的匹配規則
category 要求 Intent 可以沒有 category,但是如果一旦有 category,不管有幾個,每隔都要能和規律規則中的任何一個 category 相同。
3. date 的匹配規則
匹配規則類似於 action,要求 Intent 中必須要有 data 數據,並且 data 數據能夠完全匹配過濾規則中的某一個 data。
語法如下:

                <data 
                    android:scheme="string"
                    android:host="string"
                    android:port="string"
                    android:path="string"
                    android:pathPattern="string"
                    android:pathPrefix="string"
                    android:mimeType="string"/>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章