Activity生命週期、啓動模式、IntentFilter詳解

生命週期

1、各狀態描述
onCreate:
表示Activity開始創建。一般在裏面做一些數據初始化的操作;

onStart:
表示Activity正在啓動,即將進入前臺。這個時候Activity已經創建出來了,但是還沒有進入前臺,無法與用戶交互;

onRestart:
表示Activity正在重新啓動。從不可見狀態(onStop狀態)重新回到可見狀態時,會調用回調這個方法;

onResume:
表示Activity已經進入前臺,能夠與用戶進行交互;

onPause:
表示Activity即將停止。從完全可見狀態變爲部分可見狀態時會回調這個方法;

onStop:
表示Activity正在停止。從部分可見狀態變爲不可見狀態(從前臺到後臺)時,會回調這個方法;

onDestroy:
表示Activity正在銷燬。這是Activity生命週期的最後一個方法,一般在這個方法裏做一些資源回收的工作;

注:
onStart和onStop是從Activity是否可見這個角度來回調的,onResume和onPause是從Activity是否位於前臺這個角度來回調的,除了這個區別,實際使用過程中沒有其它明顯區別。

2、正常情況生命週期詳解
啓動一個Activity:
onCreate - onStart - onResume;

從Activity回到Home:
onPause - onStop;

從舊Activity啓動新Activity:
舊Activity執行onPause - onStop完成後, 新Activity執行onCreate - onStart - onResume。如果新Activity使用透明背景,舊Activity不會執行onStop方法;

從新Activity返回舊Activity:
新Activity執行onPause - onStop - onDestroy,舊Activity執行onRestart - onStart - onResume。如果新Activity使用透明背景,舊Activity不會執行onRestart和onStart方法,直接onResume;

3、兩種異常情況
① 內存不足導致Activity被殺死,然後再恢復;
② 配置改變導致Activity被殺死(比如屏幕方向改變),然後重新恢復;

這兩種異常情況下,Activity被殺死的回調順序是:
onPause和onSaveInstanceState(這兩個方法調用沒有固定順序) - onstop - onDestroy;

Activity重新恢復的回調順序是:
onCreate - onStart - onResume和onRestoreInstanceState(這兩個方法沒有固定順序)

對於第二種異常情況,可以通過在manifest中設置Activity標籤下的configChanges屬性,來設置其是否重啓Activity。比如設置”android:configChanges = “orientation”後,屏幕方向改變時,不會重啓Activity,而是回調Activity的onConfigurationChanged()方法。

4、數據保存
Activity被殺死時,有兩種數據需要保存,一種是控件的狀態,一種是用戶產生的數據。

對於控件的狀態,系統已經幫我們自動保存了。Activity回調onSaveInstanceState方法,這個方法裏,會委託Window去保存數據,Window又委託最頂層的DecorView,DecorView再通知其子控件調用onSaveInstanceState保存數據。

對於用戶產生的數據,需要我們重寫onSaveInstanceState,把需要保存的數據存入Bundle中,然後再重啓Acitvity時,這個Bundle會同時傳入onCreate和ononRestoreInstanceState中,我們在這兩個方法裏都能獲取到。

Activity啓動模式

Activity的啓動特性有兩種:一種是“是否重新創建”,一種“放在哪個任務棧”。

在Manifest中,LaunchMode屬性控制Activity“是否重新創建”,TaskAffinity屬性則是控制“任務棧”的,這兩個屬性可以同時生效。

在代碼中,啓動Activity時,通過intent.addFlag()來添加各種Flag,每一種Flag都包含了Activity“是否重新創建”和“放在哪個任務棧”兩個屬性,還包含一些其它特性,後面會提到。通過該方法設置模式會覆蓋manifest中的模式。

1、LaunchMode
standard:
標準模式,這是系統默認模式。每次啓動Activity都會創建一個新的實例。

singleTop:
棧頂複用模式。如果Activity已經位於棧頂,則不會調用onCreate方法重建,只會調用onNewIntent方法啓動;如果Acitvity不在棧頂,則重新創建;

singleTask:
棧內複用模式。通過一些方法可以指定Activity所在的棧(比如taskAffinity屬性、FLAG等),如果Activity已經存在於指定棧中,則不會重建,只會調用onNewIntent方法,並銷燬該Activity上面的Activity,讓其處於棧頂;如果不存在指定棧指定棧中不存在該Activity,則在指定棧中重新創建;

singleInstance:
單例模式。如果Activity不存在(任何棧中都沒有),就爲該Activity創建一個棧,並創建該Activity;如果已經存在,就調用onNewIntent方法;在這個Activity中啓動其它Activity,其它Acitivity不會在該棧中(具體在哪個棧取決於設置),該Acitivty是獨佔一個棧的。

2、任務棧相關
關於任務棧,有下面幾條規則:
① 默認情況下,所有Activity都處於默認任務棧中,任務棧名就是包名;

② 默認情況下,新Activity與啓動它的Activity在同一個棧中。所以,即使設置了TaskAffinity屬性,也不會生效;

③ 當LaunchMode爲singleTask、singleInstance時,設置TaskAffinity屬性,新Acitvity就會在TaskAffinity屬性指定的任務棧中創建;

④ 當Manifest中設置了allowTaskReparenting屬性爲true時,該Activity允許“轉移任務棧”。舉個例子來說明“轉移任務棧”,應用A啓動應用B中的某個Activity,此時,該Activity是由應用A啓動,所以該Activity在應用A的任務棧中。然後點擊Home鍵,從Home頁面點擊應用B圖標時,啓動B應用,不會啓動MainActiviy,而是創建任務棧,把已被應用A啓動的Activity轉移到該任務棧中;

⑤ 從源碼可以看出,只有發生resetTask時,纔會發生“轉移任務棧”,從Home頁點擊應用圖標時,intent都會添加FLAG_ACTIVITY_RESET_TASK_IF_NEEDED屬性,會發生“轉移任務棧”;

3、Flag
Flag會設置多種屬性,Flag值有很多,下面介紹幾種常用的Flag。

FLAG_ACTIVITY_NEW_TASK:
與Manifest中設置singleTask效果一樣;

FLAG_ACTIVITY_SINGLE_TOP:
與Manifest中設置singleTop效果一樣;

FLAG_ACTIVITY_CLEAR_TOP:
如果該Activity已經存在,則銷燬該Activity上面的Activity,然後再按照Manifest中設置launchMode來啓動該Activity;如果該Activity不存在,就按launchMode來啓動;

FLAG_ACTIVITY_NO_HISTORY:
原Activity1通過該flag啓動Activity2,Activity2不會加入到原有棧中,但是通過Activity2啓動Activity3時,Activity3又會加入原有棧中。通過返回鍵回退時,會跳過Activity2

IntentFilter

在Manifest中,通過設置Activity的intentFilter屬性,來規定該Activity隱式啓動的規則,當某個Intent能夠與intentFilter中的內容匹配時,該Activity就會被啓動。

先看Manifest中的格式

<intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <action android:name="android.intent.action.MAIN2" />
        <category android:name="android.intent.category.LAUNCHER" />
        <category android:name="android.intent.category.LAUNCHER2" />
        <data android:mimeType = "xxx/yyy"
                android:scheme = ""
                android:host = ""
                android:port = ""
                android:path = "">
</intent-filter>

intentFilter有三個標籤:action、category、data,可以有多個action、多個category,只能有一個data

1、action的匹配規則
如果intentFilter中定義了action,intent中必就須有action,intent中的action只需要與filter中的其中任意一個匹配,就算成功;
如果intentFilter中沒有定義action,那麼不會進行匹配(算匹配成功)。

2、category的匹配規則
不管intentFilter中有沒有category,如果intent中添加了category屬性,添加的所有category都必須能對應到intentFilter中的category,纔算成功;
如果intent中沒有category,也算匹配成功。

2、data的匹配規則
如果intentFilter中定義了data,intent中必就須有data,intent中的data只需要與filter中的其中任意一個匹配,就算成功。
如果intentFilter中沒有定義data,那麼不會進行匹配(算匹配成功)。

如果這三種情況都匹配成功(匹配成功標準見上面),就可啓動這個Activity了

發佈了35 篇原創文章 · 獲贊 52 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章