Activity的启动模式有两种:一种是在AndroidManifest.xml文件中,配置launchMode属性,还有一种是设置intent的flag的方式来启动
1、设置android:launchMode属性
可以分为四种:standard、singleTop、singleTask、singleInstance
standard:默认值。系统不考虑此Activity的实例是否已经在Back Stack中存在。每次创建都会启动一个新的Activity
singleTop:启动时,栈顶刚好就是目标Activity,则调用此Activity的onNewIntent()即可。如果不是,则创建新的Activity实例
singleTask:整个应用程序的上下文只有一个实例。当启动此类Activity的时候,系统会从Back Stack中检查是否已经存在此Activity的实例。 如果存在,会直接使用,并将此实例之上的Activity出栈,依然会毁掉onNewIntent().如果没有就会创建一个新的实例。
singleInstance:此Activity独享一个Back Stack。主要用于程序之间的数据共享。
下面以例子来解释:
具体的代码的设定模式如下:
<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 singleTop 栈顶复用:
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:
1.2 singleTask 栈内复用
启动步骤为: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流程。(栈内复用)
1.2.1 使用taskAffinity属性
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模式使用,才会有效果。(书上说的,需要自己去验证)
1.3 singleInstance单实例模式
以下涉及到的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>
1.3.1 在普通Activity跳转到singleInstance的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的任务栈来单独存放,并作为前台任务栈
1.3.1.1 在singleInstance的Activity跳转到普通Activity
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}
1.3.1.2 点击返回按钮
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}
1.3.1.2 点击返回按钮
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}
1.3.2 在singleInstance的Activity跳转到SingleTop的Activity
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}
1.3.3 在singleInstance的Activity跳转到SingleTask的Activity
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}
1.3.4 在singleInstance的Activity跳转到SingleTask+AffinityActivity
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}
1.3.5 在singleInstance的Activity跳转到 singleInstance的Activity
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相关的生命周期方法
2、设置intent的Flag属性
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属性这种方式