Activity的啓動模式有兩種:一種是在AndroidManifest.xml文件中,配置launchMode屬性,還有一種是設置intent的flag的方式來啓動java
能夠分爲四種:standard、singleTop、singleTask、singleInstanceandroid
standard:默認值。系統不考慮此Activity的實例是否已經在Back Stack中存在。每次建立都會啓動一個新的Activityshell
singleTop:啓動時,棧頂恰好就是目標Activity,則調用此Activity的onNewIntent()便可。若是不是,則建立新的Activity實例spa
singleTask:整個應用程序的上下文只有一個實例。當啓動此類Activity的時候,系統會從Back Stack中檢查是否已經存在此Activity的實例。 若是存在,會直接使用,並將此實例之上的Activity出棧,依然會毀掉onNewIntent().若是沒有就會建立一個新的實例。翻譯
singleInstance:此Activity獨享一個Back Stack。主要用於程序之間的數據共享。code
下面以例子來解釋:xml
具體的代碼的設定模式以下:生命週期
<activity android:name=".launchmodeTest.StandardAActivity" android:label="A"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".launchmodeTest.SingleTopActivity" android:launchMode="singleTop" android:label="棧頂複用"/> <activity android:name=".launchmodeTest.SingleTaskActivity" android:launchMode="singleTask" android:label="棧內複用"/> <activity android:name=".launchmodeTest.SingleInstanceActivity" android:launchMode="singleInstance" android:label="單獨的一個棧"/> <activity android:name=".launchmodeTest.StandardCActivity" android:label="C"></activity>
1.1.1 啓動步驟爲:StandardAActivity-->SingleTopActivity-->StandardCActivity-->SingleTopActivity進程
執行adb shell dumpsys activity命令,在堆棧中的代碼爲(截取了其中一部分):字符串
Running activities (most recent first): TaskRecord{528b8768 #5 A base.example.com U 0} Run #4: ActivityRecord{528ddc64 u0 base.example.com/.launchmodeTest.SingleTopActivity} Run #3: ActivityRecord{52897c50 u0 base.example.com/.launchmodeTest.StandardCActivity} Run #2: ActivityRecord{5288e658 u0 base.example.com/.launchmodeTest.SingleTopActivity} Run #1: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.StandardAActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
分析說明:
a、其中有兩個堆棧:
前臺堆棧:TaskRecord{528d7cd8 #6 A base.example.com U 0}
後臺堆棧:TaskRecord{528c8b7c #2 A com.android.launcher U 0}
b、桌面:Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
1.1.2 啓動步驟爲:StandardAActivity-->SingleTopActivity-->SingleTopActivity
執行adb shell dumpsys activity命令,在堆棧中的代碼爲(截取了其中一部分):
Running activities (most recent first): TaskRecord{528d7cd8 #6 A base.example.com U 0} Run #2: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.SingleTopActivity} Run #1: ActivityRecord{528b78c0 u0 base.example.com/.launchmodeTest.StandardAActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
能夠看到,SingleTopActivity兩次啓動,可是只有一個實例。
其中,生命週期爲
11-28 03:22:01.499 1831-1831/base.example.com I/SingleTopActivity: onPause: 11-28 03:22:01.499 1831-1831/base.example.com I/SingleTopActivity: onNewIntent: 11-28 03:22:01.499 1831-1831/base.example.com I/SingleTopActivity: onResume:
啓動步驟爲:StandardAActivity-->SingleTaskActivity-->StandardCActivity
堆棧爲:
Running activities (most recent first): TaskRecord{528764c0 #8 A base.example.com U 0} Run #3: ActivityRecord{5289a4a0 u0 base.example.com/.launchmodeTest.StandardCActivity} Run #2: ActivityRecord{52889940 u0 base.example.com/.launchmodeTest.SingleTaskActivity} Run #1: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.StandardAActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
再啓動SingleTaskActivity
堆棧爲:
Running activities (most recent first): TaskRecord{528764c0 #8 A base.example.com U 0} Run #2: ActivityRecord{52889940 u0 base.example.com/.launchmodeTest.SingleTaskActivity} Run #1: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.StandardAActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
可見,其中StandardCActivity被從堆棧中移除,其生命週期爲:
11-28 04:13:09.295 2163-2163/base.example.com I/StandardCActivity: onPause: 11-28 04:13:09.311 2163-2163/base.example.com I/SingleTaskActivity: onNewIntent: 11-28 04:13:09.311 2163-2163/base.example.com I/SingleTaskActivity: onStart: 11-28 04:13:09.311 2163-2163/base.example.com I/SingleTaskActivity: onResume: 11-28 04:13:09.343 2163-2163/base.example.com W/EGL_genymotion: eglSurfaceAttrib not implemented 11-28 04:13:09.719 2163-2163/base.example.com I/StandardCActivity: onStop: 11-28 04:13:09.719 2163-2163/base.example.com I/StandardCActivity: onDestroy:
可見,直接將SingleTaskActivity上面的StandardCActivity移除,並調用了本身的onNewIntent()方法。StandardCActivity本身走了本身的destroy流程。(棧內複用)
taskAffinity屬性能夠翻譯爲任務相關性,主要表示的是此Activity的進程名字(默認進程是包名)。其中的值必須爲字符串,而且包含「.」
例如以下定義:
<activity android:name=".launchmodeTest.SingleTaskWithAffinityActivity" android:launchMode="singleTask" android:taskAffinity="com.cxy.test"></activity>
啓動後的棧爲:StandardAActivity-->SingleTaskWithAffinityActivity
Running activities (most recent first): TaskRecord{528e7e2c #12 A com.cxy.test U 0} Run #2: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.SingleTaskWithAffinityActivity} TaskRecord{528c7a48 #11 A base.example.com U 0} Run #1: ActivityRecord{5276bcd4 u0 base.example.com/.launchmodeTest.StandardAActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
再啓動一個standard模式的Activity:StandardAActivity-->SingleTaskWithAffinityActivity-->StandardCActivity
Running activities (most recent first): TaskRecord{528e7e2c #12 A com.cxy.test U 0} Run #3: ActivityRecord{52889940 u0 base.example.com/.launchmodeTest.StandardCActivity} Run #2: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.SingleTaskWithAffinityActivity} TaskRecord{528c7a48 #11 A base.example.com U 0} Run #1: ActivityRecord{5276bcd4 u0 base.example.com/.launchmodeTest.StandardAActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
能夠查看出來,誰啓動的Activity,就會在誰的棧中添加對應的Activity。除非被啓動的Activity已經制定了進程名。
再次啓動SingleTaskWithAffinityActivity:StandardAActivity-->SingleTaskWithAffinityActivity-->SingleTaskWithAffinityActivity
Running activities (most recent first): TaskRecord{528e7e2c #12 A com.cxy.test U 0} Run #2: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.SingleTaskWithAffinityActivity} TaskRecord{528c7a48 #11 A base.example.com U 0} Run #1: ActivityRecord{5276bcd4 u0 base.example.com/.launchmodeTest.StandardAActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
生命週期:
11-28 04:37:02.595 2411-2411/base.example.com I/StandardCActivity: onPause: 11-28 04:37:02.607 2411-2411/base.example.com I/SingleTaskWithAffinityA: onNewIntent: 11-28 04:37:02.607 2411-2411/base.example.com I/SingleTaskWithAffinityA: onStart: 11-28 04:37:02.611 2411-2411/base.example.com I/SingleTaskWithAffinityA: onResume: 11-28 04:37:02.647 2411-2411/base.example.com W/EGL_genymotion: eglSurfaceAttrib not implemented 11-28 04:37:03.019 2411-2411/base.example.com I/StandardCActivity: onStop: 11-28 04:37:03.019 2411-2411/base.example.com I/StandardCActivity: onDestroy:
可見調用了SingleTaskWithAffinityActivity的onNewIntent()、onStart()、onResume()方法。並將StandardCActivity從堆棧中移除了。
再次啓動SingleTaskActivity:StandardAActivity-->SingleTaskWithAffinityActivity-->StandardCActivity-->SingleTaskActivity
Running activities (most recent first): TaskRecord{528321b0 #13 A base.example.com U 0} Run #4: ActivityRecord{5292dca8 u0 base.example.com/.launchmodeTest.SingleTaskActivity} TaskRecord{5288a210 #14 A com.cxy.test U 0} Run #3: ActivityRecord{528ddc64 u0 base.example.com/.launchmodeTest.StandardCActivity} Run #2: ActivityRecord{5288e658 u0 base.example.com/.launchmodeTest.SingleTaskWithAffinityActivity} TaskRecord{528321b0 #13 A base.example.com U 0} Run #1: ActivityRecord{52889940 u0 base.example.com/.launchmodeTest.StandardAActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
可見設置了singleTask模式的activity,會在原來的堆棧中。
假設給standard模式的activity設置taskAffinity屬性
<activity android:name=".launchmodeTest.StandardCActivity" android:label="C" android:taskAffinity="com.cxy.test.one"/>
啓動的結果爲:StandardAActivity-->SingleTaskWithAffinityActivity-->StandardCActivity
Running activities (most recent first): TaskRecord{5276b448 #16 A com.cxy.test U 0} Run #3: ActivityRecord{5288e658 u0 base.example.com/.launchmodeTest.StandardCActivity} Run #2: ActivityRecord{528ddc64 u0 base.example.com/.launchmodeTest.SingleTaskWithAffinityActivity} TaskRecord{528d42c4 #15 A base.example.com U 0} Run #1: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.StandardAActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
taskAffinity必須與singleTask模式使用,纔會有效果。(書上說的,須要本身去驗證)
如下涉及到的activity的定義:
<activity android:name=".launchmodeTest.StandardAActivity" android:label="A"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".launchmodeTest.SingleTopActivity" android:label="棧頂複用" android:launchMode="singleTop" /> <activity android:name=".launchmodeTest.SingleTaskActivity" android:label="棧內複用" android:launchMode="singleTask" /> <activity android:name=".launchmodeTest.SingleInstanceActivity" android:label="單獨的一個棧" android:launchMode="singleInstance" /> <activity android:name=".launchmodeTest.StandardCActivity" android:label="C"/> <activity android:name=".launchmodeTest.SingleTaskWithAffinityActivity" android:launchMode="singleTask" android:taskAffinity="com.cxy.test"></activity>
StandardAActivity-->SingleInstanceActivity
Running activities (most recent first): TaskRecord{52885efc #18 A base.example.com U 0} Run #2: ActivityRecord{52937648 u0 base.example.com/.launchmodeTest.SingleInstanceActivity} TaskRecord{52897aa0 #17 A base.example.com U 0} Run #1: ActivityRecord{528a6334 u0 base.example.com/.launchmodeTest.StandardAActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
直接新啓動了一個編號爲18的任務棧來單獨存放,並做爲前臺任務棧
StandardAActivity-->SingleInstanceActivity-->StandardCActivity
Running activities (most recent first): TaskRecord{52897aa0 #17 A base.example.com U 0} Run #3: ActivityRecord{52905030 u0 base.example.com/.launchmodeTest.StandardCActivity} TaskRecord{52885efc #18 A base.example.com U 0} Run #2: ActivityRecord{52937648 u0 base.example.com/.launchmodeTest.SingleInstanceActivity} TaskRecord{52897aa0 #17 A base.example.com U 0} Run #1: ActivityRecord{528a6334 u0 base.example.com/.launchmodeTest.StandardAActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
Running activities (most recent first): TaskRecord{52897aa0 #17 A base.example.com U 0} Run #2: ActivityRecord{528a6334 u0 base.example.com/.launchmodeTest.StandardAActivity} TaskRecord{52885efc #18 A base.example.com U 0} Run #1: ActivityRecord{52937648 u0 base.example.com/.launchmodeTest.SingleInstanceActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
Running activities (most recent first): TaskRecord{52885efc #18 A base.example.com U 0} Run #1: ActivityRecord{52937648 u0 base.example.com/.launchmodeTest.SingleInstanceActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
StandardAActivity-->SingleInstanceActivity-->SingleTopActivity
Running activities (most recent first): TaskRecord{528864b0 #21 A base.example.com U 0} Run #3: ActivityRecord{5288e658 u0 base.example.com/.launchmodeTest.SingleTopActivity} TaskRecord{5289313c #22 A base.example.com U 0} Run #2: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.SingleInstanceActivity} TaskRecord{528864b0 #21 A base.example.com U 0} Run #1: ActivityRecord{5276bcd4 u0 base.example.com/.launchmodeTest.StandardAActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
StandardAActivity-->SingleInstanceActivity-->SingleTaskActivity
Running activities (most recent first): TaskRecord{52863e64 #23 A base.example.com U 0} Run #3: ActivityRecord{528acda4 u0 base.example.com/.launchmodeTest.SingleTaskActivity} TaskRecord{52830620 #24 A base.example.com U 0} Run #2: ActivityRecord{528aaa88 u0 base.example.com/.launchmodeTest.SingleInstanceActivity} TaskRecord{52863e64 #23 A base.example.com U 0} Run #1: ActivityRecord{528aa754 u0 base.example.com/.launchmodeTest.StandardAActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
StandardAActivity-->SingleInstanceActivity-->SingleTaskWithAffinityActivity
Running activities (most recent first): TaskRecord{528cbc48 #27 A com.cxy.test U 0} Run #3: ActivityRecord{5288e658 u0 base.example.com/.launchmodeTest.SingleTaskWithAffinityActivity} TaskRecord{52832ec8 #26 A base.example.com U 0} Run #2: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.SingleInstanceActivity} TaskRecord{528c7cc0 #25 A base.example.com U 0} Run #1: ActivityRecord{5276bcd4 u0 base.example.com/.launchmodeTest.StandardAActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
StandardAActivity-->SingleInstanceActivity-->SingleInstanceActivity
Running activities (most recent first): TaskRecord{528009a8 #29 A base.example.com U 0} Run #2: ActivityRecord{528acda4 u0 base.example.com/.launchmodeTest.SingleInstanceActivity} TaskRecord{528ac1bc #28 A base.example.com U 0} Run #1: ActivityRecord{528aa754 u0 base.example.com/.launchmodeTest.StandardAActivity} TaskRecord{528c8b7c #2 A com.android.launcher U 0} Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}
對應的生命週期爲:
11-28 08:07:00.135 3369-3369/base.example.com I/SingleInstanceActivity: onPause: 11-28 08:07:00.135 3369-3369/base.example.com I/SingleInstanceActivity: onNewIntent: 11-28 08:07:00.135 3369-3369/base.example.com I/SingleInstanceActivity: onResume:
總結:singleInstance的Activity只會單獨存放在一個堆棧中。而且對此啓動都不會再次建立,只會調用onNewIntent相關的生命週期方法
FLAG_ACTIVITY_NEW_TASK:使用一個新的task來啓動Activity。一般使用在service中啓動Activity
FLAG_ACTIVITY_SINGLE_TOP:使用singleTop模式來啓動Activity
FLAG_ACTIVITY_CLEAR_TOP:使用singleTask模式來啓動Activity
FLAG_ACTIVITY_NO_HISTORY:使用此模式啓動的Activity,該Activity啓動完其餘Activity之後,此Activity會從棧中消失
還有一些其餘的屬性,須要本身去試一下。
注意:
(1)、在優先級上:以上兩種啓動模式,設置intent的flag屬性的優先級會更高。
(2)、在限定範圍上,設置android:launchMode屬性這種方式,沒法爲Activity設定FLAG_ACTIVITY_CLEAR_TOP標誌。
設置intent的Flag屬性的方式,沒法指定singleInstance的方式。
(3)、非特殊狀況,儘可能使用設置android:launchMode屬性這種方式