Android 启动模式

四种启动模式

  • standard(标准模式)

  • singleTop(栈顶复用模式)

  • singleTask(栈内复用模式)

  • singleInstance(单一实例模式)

standard标准模式

每次开启activity都会创建新的实例,不管这个实例是否已经存在任务栈中,

image.png

如果在 AndroidManifest.xml 中将 Activity B 的启动模式设置为 Standard,不管任务栈内是否已经存在 Activity B 的实例,当启动 Activity B 时,都会创建一个崭新的 Activity B 位于任务栈顶

例如
// 启动顺序
MainActivity -> StandardActivity -> StandardActivity
​
// 栈内容(adb shell dumpsys activity activities)
Running activities (most recent first):
    TaskRecord{b4e290f #18017 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=3}
    Run #2: ActivityRecord{1666db1 u0 com.wuzy.androidlaunchmodetest/.StandardActivity t18017}
    Run #1: ActivityRecord{17fa3e6 u0 com.wuzy.androidlaunchmodetest/.StandardActivity t18017}
    Run #0: ActivityRecord{9e18184 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18017}

singleTop(栈顶复用模式)

SingleTop与Standard模式类似,使用SingleTop模式可以创建多个Activity的实例。不同于Standard模式在于,如果这个Activity处于当前任务栈的栈顶,则不会创建新的实例,而是复用栈顶的实例,intent会通过onNewIntent方法传递到这个activity。

image.png

如果在 AndroidManifest.xml 中将 Activity D 的启动模式设置为 SingleTop 并且任务栈内存在 Activity D 实例且位于栈顶时,当启动 Activity D 时,会复用之前创建的 Activity D 的实例,并且 onNewIntent() 方法被调用

image.png

如果在 AndroidManifest.xml 中将 Activity D 的启动模式设置为 SingleTop 并且任务栈内并不存在 Activity D 的实例时,当启动 Activity D 时,会创建一个崭新的 Activity D 实例在栈顶

image.png

如果在 AndroidManifest.xml 中将 Activity D 的启动模式设置为 SingleTop 并且任务栈内存在 Activity D 的实例但其实例未在栈顶时,当启动 Activity D 时,会再次创建一个崭新的 Activity D 实例在栈顶

例如
例 1:
// 启动顺序
MainActivity -> SingleTopActivity -> SingleTopActivity
​
// 栈内容
Running activities (most recent first):
    TaskRecord{9de11c2 #18073 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=2}
    Run #1: ActivityRecord{f0acc0c u0 com.wuzy.androidlaunchmodetest/.SingleTopActivity t18073}
    Run #0: ActivityRecord{b884d57 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18073}
    
-----------------------------------------------------------------------------------------
​
例 2:
// 启动顺序
MainActivity -> SingleTopActivity -> StandardActivity -> SingleTopActivity
​
// 栈内容
Running activities (most recent first):
    TaskRecord{9de11c2 #18073 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=4}
    Run #3: ActivityRecord{c282b33 u0 com.wuzy.androidlaunchmodetest/.SingleTopActivity t18073}
    Run #2: ActivityRecord{76fb23e u0 com.wuzy.androidlaunchmodetest/.StandardActivity t18073}
    Run #1: ActivityRecord{b6969a8 u0 com.wuzy.androidlaunchmodetest/.SingleTopActivity t18073}
    Run #0: ActivityRecord{b884d57 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18073}

例 1 中由于栈顶已经是 SingleTopActivity,再启动 SingleTopActivity 时直接复用了栈顶 Activity,无需创建新的实例。

例 2 中第二次启动 SingleTopActivity 时,由于栈顶是 StandardActivity,所以启动 SingleTopActivity 时会创建新的实例。

singleTask 栈内复用模式

如果当前任务栈没有这个Activity,则这个Activity直接加入到任务栈中。如果当前任务栈内有这个Activity实例,不管Activity在什么位置都会复用这个Activity,这个Activity上的所有Activity都会移除任务栈,intent通过onNewIntent传递到这个Activity。

image.png

如果在 AndroidManifest.xml 中将 Activity C 的启动模式设置为 SingleTask,如果此时任务栈内已经存在 Activity C 的实例且未位于栈顶,当启动 Activity C 时,会将 Activity C 上方的实例全部出栈让其位于任务栈顶并 Activity C 中的 onNewIntent() 方法会被调用

image.png

如果在 AndroidManifest.xml 中将 Activity C 的启动模式设置为 SingleTask,并且此时任务栈内并不存在 Activity C 的实例,当启动 Activity C 时,会创建一个崭新的 Activity C 实例在栈顶

例如
// 1、启动顺序
MainActivity -> SingleTaskActivity -> StandardActivity
​
// 栈内容:
Running activities (most recent first):
    TaskRecord{ebb2593 #18095 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=3}
    Run #2: ActivityRecord{49b6bb8 u0 com.wuzy.androidlaunchmodetest/.StandardActivity t18095}
    Run #1: ActivityRecord{48628d2 u0 com.wuzy.androidlaunchmodetest/.SingleTaskActivity t18095}
    Run #0: ActivityRecord{86fe71f u0 com.wuzy.androidlaunchmodetest/.MainActivity t18095}
​
-----------------------------------------------------------------------------------------
​
// 2、启动顺序
MainActivity -> SingleTaskActivity -> StandardActivity -> SingleTaskActivity
​
// 栈内容
Running activities (most recent first):
    TaskRecord{ebb2593 #18095 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=2}
    Run #1: ActivityRecord{48628d2 u0 com.wuzy.androidlaunchmodetest/.SingleTaskActivity t18095}
    Run #0: ActivityRecord{86fe71f u0 com.wuzy.androidlaunchmodetest/.MainActivity t18095}

可以看到,在第二次启动 SingleTaskActivity 时,由于栈内已经存在了 SingleTaskActivity 实例,栈顶 StandardActivity 被移出任务栈,复用了栈内 SingleTaskActivity 实例。

当以 singleTask 启动一个 Activity 的时候,首先去判断是否要为该 Activity 去创建一个任务栈?如果需要的话,那么就会创建一个任务栈,并且将该 Activity 放入栈中;如果不需要的话,直接将该 Activity 放入当前的任务栈中。

那么如何判断要不要为 singleTask Activity 创建一个任务栈?

任务栈的创建跟 taskAffinity 的属性相关,每个 Activity 都有 taskAffinity 属性,这个属性指出了它希望进入的任务栈。如果一个 Activity 没有显式的指明该 Activity 的 taskAffinity,那么它的这个属性就等于 Application 指明的 taskAffinity,如果 Application 也没有指明,那么该 taskAffinity 的值就等于包名。

这里我指定一下 Activity 的 taskAffinity :

<activity
    android:name=".SingleTaskWithAffinityActivity"
    android:label="SingleTaskWithAffinity Activity"
    android:launchMode="singleTask"
    android:taskAffinity="com.jaqen" />

看一下测试结果:

// 1、启动顺序
MainActivity -> SingleTaskWithAffinityActivity
​
// 任务栈
Running activities (most recent first):
    TaskRecord{fa7e695 #18097 A=com.jaqen U=0 StackId=1 sz=1}
    Run #1: ActivityRecord{6267f33 u0 com.wuzy.androidlaunchmodetest/.SingleTaskWithAffinityActivity t18097}
    TaskRecord{efcc3aa #18096 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=1}
    Run #0: ActivityRecord{ccdada8 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18096}
    
-----------------------------------------------------------------------------------------
​
// 2、启动顺序
MainActivity -> SingleTaskWithAffinityActivity -> StandardActivity
​
// 栈内容
Running activities (most recent first):
    TaskRecord{3f4af35 #18097 A=com.jaqen U=0 StackId=1 sz=2}
    Run #2: ActivityRecord{23b4c1a u0 com.wuzy.androidlaunchmodetest/.StandardActivity t18097}
    Run #1: ActivityRecord{d234ee0 u0 com.wuzy.androidlaunchmodetest/.SingleTaskWithAffinityActivity t18097}
    TaskRecord{e27d53b #18096 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=1}
    Run #0: ActivityRecord{f445d23 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18096}
​
-----------------------------------------------------------------------------------------
​
// 3、启动顺序
MainActivity -> SingleTaskWithAffinityActivity -> StandardActivity -> SingleTaskWithAffinityActivity
​
// 栈内容
Running activities (most recent first):
    TaskRecord{3f4af35 #18097 A=com.jaqen U=0 StackId=1 sz=1}
    Run #1: ActivityRecord{d234ee0 u0 com.wuzy.androidlaunchmodetest/.SingleTaskWithAffinityActivity t18097}
    TaskRecord{e27d53b #18096 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=1}
    Run #0: ActivityRecord{f445d23 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18096}

首次启动 SingleTaskWithAffinityActivity 会创建新的任务栈(大括号内 # 后的数字标识任务栈 id)。

在 SingleTaskWithAffinityActivity 启动 StandardActivity , 这个 StandardActivity 与 SingleTaskWithAffinityActivity 在同一个栈。

SingleTaskWithAffinityActivity 会出现在多任务界面。

第二次启动 SingleTopActivity 时直接复用了栈内已存 Activity,已存 Activity 上的 Activity 被移出任务栈。

singleInstance 单实例模式

在应用中只能有一个实例,存放singleInstance模式的activity实例的任务栈只能存放唯一的singleInstance Activity。

image.png

如果在 AndroidManifest.xml 中将 Activity E 的启动模式设置为 SingleInstance,并且任务栈内不存在 Activity E 的实例,当启动 Activity E 时,会在创建一个新的任务栈,并且栈内只有 Activity E 一个实例

例如
// 1、启动顺序
MainActivity -> SingleInstanceActivity
​
// 栈内容
Running activities (most recent first):
    TaskRecord{cd22626 #18116 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=1}
    Run #1: ActivityRecord{462d9a2 u0 com.wuzy.androidlaunchmodetest/.SingleInstanceActivity t18116}
    TaskRecord{c2b08bd #18115 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=1}
    Run #0: ActivityRecord{812c79c u0 com.wuzy.androidlaunchmodetest/.MainActivity t18115}
    
-----------------------------------------------------------------------------------------
​
// 2、启动顺序
MainActivity -> SingleInstanceActivity -> StandardActivity
​
// 栈内容
Running activities (most recent first):
    TaskRecord{e46fd18 #18115 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=2}
    Run #2: ActivityRecord{540b885 u0 com.wuzy.androidlaunchmodetest/.StandardActivity t18115}
    TaskRecord{5cab9d7 #18116 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=1}
    Run #1: ActivityRecord{18780a3 u0 com.wuzy.androidlaunchmodetest/.SingleInstanceActivity t18116}
    TaskRecord{e46fd18 #18115 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=2}
    Run #0: ActivityRecord{6ceacf3 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18115}
    
-----------------------------------------------------------------------------------------
​
// 3、启动顺序
MainActivity -> SingleInstanceActivity -> StandardActivity -> SingleInstanceActivity
​
// 栈内容
Running activities (most recent first):
    TaskRecord{e46fd18 #18115 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=2}
    Run #2: ActivityRecord{540b885 u0 com.wuzy.androidlaunchmodetest/.StandardActivity t18115}
    TaskRecord{5cab9d7 #18116 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=1}
    Run #1: ActivityRecord{18780a3 u0 com.wuzy.androidlaunchmodetest/.SingleInstanceActivity t18116}
    TaskRecord{e46fd18 #18115 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=2}
    Run #0: ActivityRecord{6ceacf3 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18115}

启动 SingleInstanceActivity 会创建新的任务栈,从 SingleInstanceActivity 中启动 StandardActivity,StandardActivity 会被放到上一个任务栈中。

再此启动 SingleInstanceActivity,SingleInstanceActivity 会被复用。

使用场景

singleInstance 模式常应用于独立栈操作的应用,如闹钟的提醒页面,当你在A应用中看视频时,闹钟响了,你点击闹钟提醒通知后进入提醒详情页面,然后点击返回就再次回到A的视频页面,这样就不会过多干扰到用户先前的操作了。

Intent Flags

除了在 manifest 文件中设置 launchMode 之外,还可以在 Intent 中设置 Flag 达到同样的效果。

Intent设置方式的优先级 > Manifest设置方式,即 以前者为准

Manifest设置方式无法设定 FLAG_ACTIVITY_CLEAR_TOP;Intent设置方式 无法设置单例模式(SingleInstance)

标记位属性 含义
FLAG_ACTIVITY_SINGLE_TOP 指定启动模式为栈顶复用模式(SingleTop)
FLAG_ACTIVITY_NEW_TASK 指定启动模式为栈内复用模式(SingleTask)
FLAG_ACTIVITY_CLEAR_TOP 所有位于其上层的Activity都要移除,SingleTask模式默认具有此标记效果
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 具有该标记的Activity不会出现在历史Activity的列表中,即无法通过历史列表回到该Activity上

FLAG_ACTIVITY_NEW_TASK

在 google 的官方文档中介绍,它与 launchMode="singleTask" 具有相同的行为。实际上,并不是完全相同!具体看下面的案例分析。

FLAG_ACTIVITY_SINGLE_TOP

等同于 launchMode="singleTop" 。

FLAG_ACTIVITY_CLEAR_TOP

删除包含目标Activity的任务栈中位于该Activity之上的所有Activity实例。复用已有的目标Activity还是先删除后重建,有一下规则:

  • 若是使用FLAG_ACTIVITY_SINGLE_TOPFLAG_ACTIVITY_CLEAR_TOP标志位组合,那么不管目标 Activity 是什么启动模式,都会被复用。

  • 若是单独使用FLAG_ACTIVITY_CLEAR_TOP那么已有非standard模式启动模式的目标 Activity 才会被复用,否则都先被删除,然后被重新创建并入栈。

FLAG_ACTIVITY_CLEAR_TASK

首先清楚目标Activity所在的任务栈,这也就清楚了之前存在的目标Activity的实例,然后重写创建新的目标activity实例并入栈。

通过几个案例查看 Flag 的使用效果。

  • MainActivity 为 standard 模式,未设置 Flag。
  • IntentFlagTestActivity 为 standard 模式,未设置 taskAffinity。
<activity
   android:name=".IntentFlagTestActivity"
   android:label="IntentFlagTestActivity" />
  • IntentFlagTestWithAffinityActivity 为 standard 模式,设置与 MainActivity 不同的 taskAffinity。

<activity android:name=".IntentFlagTestWithAffinityActivity"
    android:taskAffinity="com.jaqen"
    android:label="IntentFlagTestWithAffinityActivity"/> 
1、单独使用 FLAG_ACTIVITY_NEW_TASK
  • taskAffinity 相同时:
// 启动 IntentFlagTestActivity 的方式
Intent intent = new Intent(MainActivity.this, IntentFlagTestActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

测试结果:

// 启动流程
MainActivity -> IntentFlagTestActivity -> MainActivity -> IntentFlagTestActivity
​
// 栈内容
Running activities (most recent first):
TaskRecord{89317d5 #18128 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=4}
Run #3: ActivityRecord{2f1ac92 u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestActivity t18128}
Run #2: ActivityRecord{a0104eb u0 com.wuzy.androidlaunchmodetest/.MainActivity t18128}
Run #1: ActivityRecord{9b84b56 u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestActivity t18128}
Run #0: ActivityRecord{f9a57f4 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18128}

从任务栈可以看出,在 taskAffinity 相同的情况下,单独使用 FLAG_ACTIVITY_NEW_TASK 不会产生任何效果!

  • taskAffinity 不同时:
// 启动 IntentFlagTestWithAffinityActivity 的方式
Intent intent = new Intent(MainActivity.this, IntentFlagTestWithAffinityActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

测试结果:

// 启动流程
MainActivity -> IntentFlagTestWithAffinityActivity -> MainActivity -> IntentFlagTestWithAffinityActivity
​
// 栈内容
Running activities (most recent first):
    TaskRecord{d07e70 #18135 A=com.jaqen U=0 StackId=1 sz=2}
    Run #2: ActivityRecord{997119c u0 com.wuzy.androidlaunchmodetest/.MainActivity t18135}
    Run #1: ActivityRecord{8a7f641 u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestWithAffinityActivity t18135}
    TaskRecord{84f526e #18134 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=1}
    Run #0: ActivityRecord{5aca49d u0 com.wuzy.androidlaunchmodetest/.MainActivity t18134}

在 taskAffinity 不同的情况下, 添加 FLAG_ACTIVITY_NEW_TASK 确实产生了一些效果,第一次启动 IntentFlagTestWithAffinityActivity 创建了新的任务栈,但是第二次从 MainActivity 中启动 IntentFlagTestWithAffinityActivity 时,没有任何反应。

结论:

单独使用 FLAG_ACTIVITY_NEW_TASK 并不会产生与 singleTask 相同的效果。

2、FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP

taskAffinity 相同时:

// 启动 IntentFlagTestActivity 的方式
Intent intent = new Intent(MainActivity.this, IntentFlagTestActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

测试结果:

// 1、启动流程
MainActivity -> IntentFlagTestActivity -> MainActivity
    
// 栈内容
Running activities (most recent first):
    TaskRecord{7bb1982 #18139 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=3}
    Run #2: ActivityRecord{535c0d0 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18139}
    Run #1: ActivityRecord{c5253ff u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestActivity t18139}
    Run #0: ActivityRecord{1b04db1 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18139}

-----------------------------------------------------------------------------------------

// 2、启动流程
MainActivity -> IntentFlagTestActivity -> MainActivity -> IntentFlagTestActivity
    
// 栈内容
Running activities (most recent first):
    TaskRecord{7bb1982 #18139 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=2}
    Run #1: ActivityRecord{705bf3 u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestActivity t18139}
    Run #0: ActivityRecord{1b04db1 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18139}

在 taskAffinity 相同情况下,FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP 不会创建新的任务栈。

貌似和 singleTask 启动模式效果相同,但是细看会发现区别:前后两次 IntentFlagTestActivity 并不是同一个实例,也就是并没有复用栈内的 IntentFlagTestActivity,而是清除了 IntentFlagTestActivity 本身及其之上的所有 Activity,然后新建 IntentFlagTestActivity 实例添加到当前任务栈。

  • taskAffinity 不同时:

// 启动 IntentFlagTestWithAffinityActivity 的方式
Intent intent = new Intent(MainActivity.this, IntentFlagTestWithAffinityActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

测试结果:

// 1、启动流程
MainActivity -> IntentFlagTestWithAffinityActivity -> MainActivity

// 任务栈
Running activities (most recent first):
    TaskRecord{a1b1a38 #18152 A=com.jaqen U=0 StackId=1 sz=2}
    Run #2: ActivityRecord{ae8c352 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18152}
    Run #1: ActivityRecord{5647f4a u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestWithAffinityActivity t18152}
    TaskRecord{e2f8776 #18151 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=1}
    Run #0: ActivityRecord{864a2f5 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18151}

-----------------------------------------------------------------------------------------

// 2、启动流程
MainActivity -> IntentFlagTestWithAffinityActivity -> MainActivity -> IntentFlagTestWithAffinityActivity
    
Running activities (most recent first):
    TaskRecord{a1b1a38 #18152 A=com.jaqen U=0 StackId=1 sz=1}
    Run #1: ActivityRecord{cf5fce6 u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestWithAffinityActivity t18152}
    TaskRecord{e2f8776 #18151 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=1}
    Run #0: ActivityRecord{864a2f5 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18151}

可见,与 taskAffinity 相同类似(除了创建新的任务栈),在第二次启动 IntentFlagTestWithAffinityActivity 时也是直接清除了 IntentFlagTestWithAffinityActivity 自身及其之上所有的 Activity,然后创建新的 IntentFlagTestWithAffinityActivity 实例添加到任务栈中。

结论:

FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP 标志位组合产生的效果总体上和 singleTask 模式相同,但不会复用 Activity。

3、FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TASK

  • taskAffnity 相同时:
// 启动 IntentFlagTestActivity 的方式
Intent intent = new Intent(MainActivity.this, IntentFlagTestActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);

测试结果:

// 1、启动流程
MainActivity -> IntentFlagTestActivity

// 栈内容
Running activities (most recent first):
    TaskRecord{572ae8d #18253 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=1}
    Run #0: ActivityRecord{e0aa3a u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestActivity t18253}

-----------------------------------------------------------------------------------------

// 2、启动流程
MainActivity -> IntentFlagTestActivity  -> MainActivity

// 栈内容
Running activities (most recent first):
    TaskRecord{572ae8d #18253 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=2}
    Run #1: ActivityRecord{65fb5c2 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18253}
    Run #0: ActivityRecord{e0aa3a u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestActivity t18253}

-----------------------------------------------------------------------------------------

// 3、启动流程
MainActivity -> IntentFlagTestActivity  -> MainActivity -> IntentFlagTestActivity

// 栈内容
Running activities (most recent first):
    TaskRecord{572ae8d #18253 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=1}
    Run #0: ActivityRecord{9eccfa3 u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestActivity t18253}
    

可见, 当通过FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TASK 标志位组合启动 IntentFlagTestActivity 时,首先会清空 IntentFlagTestActivity 所在的任务栈,然后再创建新的 IntentFlagTestActivity 实例并入栈。

  • taskAffnity 不同时:
// 启动 IntentFlagTestWithAffinityActivity 的方式
Intent intent = new Intent(MainActivity.this, IntentFlagTestWithAffinityActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);

测试结果:

// 1、启动流程
MainActivity -> IntentFlagTestWithAffinityActivity

// 栈内容
Running activities (most recent first):
    TaskRecord{c081b17 #18257 A=com.jaqen U=0 StackId=1 sz=1}
    Run #1: ActivityRecord{8f8a3c5 u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestWithAffinityActivity t18257}
    TaskRecord{60908ed #18256 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=1}
    Run #0: ActivityRecord{5924b86 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18256}
    
-----------------------------------------------------------------------------------------

// 2、启动流程
MainActivity -> IntentFlagTestWithAffinityActivity -> MainActivity

// 栈内容
Running activities (most recent first):
    TaskRecord{c081b17 #18257 A=com.jaqen U=0 StackId=1 sz=2}
    Run #2: ActivityRecord{7e1a8a0 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18257}
    Run #1: ActivityRecord{8f8a3c5 u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestWithAffinityActivity t18257}
    TaskRecord{60908ed #18256 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=1}
    Run #0: ActivityRecord{5924b86 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18256}

-----------------------------------------------------------------------------------------

// 3、启动流程
MainActivity -> IntentFlagTestWithAffinityActivity -> MainActivity -> IntentFlagTestWithAffinityActivity

// 栈内容
Running activities (most recent first):
    TaskRecord{c081b17 #18257 A=com.jaqen U=0 StackId=1 sz=1}
    Run #1: ActivityRecord{e52a3c0 u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestWithAffinityActivity t18257}
    TaskRecord{60908ed #18256 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=1}
    Run #0: ActivityRecord{5924b86 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18256}

结果与 taskAffnity 相同情况下类似, 首先会清空 IntentFlagTestWithAffinityActivity 所在的任务栈,然后再创建新的 IntentFlagTestWithAffinityActivity 实例并入栈,这和 taskAffinity 属性相同是一致的效果,只不过这里第一次为 IntentFlagTestWithAffinityActivity 创建了新的任务栈。

结论:

FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TASK 标志位组会先清空任务栈,再创建新的 Activity 实例入栈。

4、单独使用 FLAG_ACTIVITY_CLEAR_TOP

  • IntentFlagTestActivity 启动模式:standard
// 1、启动流程
MainActivity -> IntentFlagTestActivity

// 栈内容
Running activities (most recent first):
    TaskRecord{b6045f3 #18282 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=2}
    Run #1: ActivityRecord{44dcf5f u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestActivity t18282}
    Run #0: ActivityRecord{c713f21 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18282}

-----------------------------------------------------------------------------------------

// 2、启动流程
MainActivity -> IntentFlagTestActivity  -> MainActivity

// 栈内容
Running activities (most recent first):
    TaskRecord{b6045f3 #18282 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=3}
    Run #2: ActivityRecord{13c806b u0 com.wuzy.androidlaunchmodetest/.MainActivity t18282}
    Run #1: ActivityRecord{44dcf5f u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestActivity t18282}
    Run #0: ActivityRecord{c713f21 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18282}

-----------------------------------------------------------------------------------------

// 3、启动流程
MainActivity -> IntentFlagTestActivity  -> MainActivity -> IntentFlagTestActivity

// 栈内容
Running activities (most recent first):
    TaskRecord{b6045f3 #18282 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=2}
    Run #1: ActivityRecord{fa6320c u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestActivity t18282}
    Run #0: ActivityRecord{c713f21 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18282}
  • IntentFlagTestActivity 启动模式:singleTask
// 1、启动流程
MainActivity -> IntentFlagTestActivity

// 栈内容
Running activities (most recent first):
    TaskRecord{7c9d493 #18280 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=2}
    Run #1: ActivityRecord{daafb1e u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestActivity t18280}
    Run #0: ActivityRecord{b547fca u0 com.wuzy.androidlaunchmodetest/.MainActivity t18280}

-----------------------------------------------------------------------------------------

// 2、启动流程
MainActivity -> IntentFlagTestActivity  -> MainActivity

// 栈内容
Running activities (most recent first):
    TaskRecord{7c9d493 #18280 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=3}
    Run #2: ActivityRecord{511762c u0 com.wuzy.androidlaunchmodetest/.MainActivity t18280}
    Run #1: ActivityRecord{daafb1e u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestActivity t18280}
    Run #0: ActivityRecord{b547fca u0 com.wuzy.androidlaunchmodetest/.MainActivity t18280}

-----------------------------------------------------------------------------------------

// 3、启动流程
MainActivity -> IntentFlagTestActivity  -> MainActivity -> IntentFlagTestActivity

// 栈内容
Running activities (most recent first):
    TaskRecord{7c9d493 #18280 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=2}
    Run #1: ActivityRecord{daafb1e u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestActivity t18280}
    Run #0: ActivityRecord{b547fca u0 com.wuzy.androidlaunchmodetest/.MainActivity t18280}

从上面两个例子看出,单独使用 FLAG_ACTIVITY_CLEAR_TOP 时,

standard 启动模式下,目标 Activity 自身及其上的 Activity 都会被销毁,目标 Activity 自身会重新创建放入栈中;singleTask 启动模式下,先销毁目标 Activity 之上的所有 Activity,然后复用已有的 Activity。

此外,singleTop、singleInstance 与 singleTask 一样,都会复用已有 Activity。这里不在赘述。

结论

单独使用 FLAG_ACTIVITY_CLEAR_TOP,那么只有非 standard 启动模式的目标 Activity 才会被复用,否则都先被删除,然后被重新创建并入栈。

5、FLAG_ACTIVITY_CLEAR_TOP + FLAG_ACTIVITY_SINGLE_TOP

  • IntentFlagTestActivity 启动模式 standard
// 1、启动流程
MainActivity -> IntentFlagTestActivity

// 栈内容
Running activities (most recent first):
    TaskRecord{bf65b55 #18326 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=2}
    Run #1: ActivityRecord{c62eb86 u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestActivity t18326}
    Run #0: ActivityRecord{eb38b03 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18326}


-----------------------------------------------------------------------------------------

// 2、启动流程
MainActivity -> IntentFlagTestActivity  -> MainActivity

// 栈内容
Running activities (most recent first):
    TaskRecord{bf65b55 #18326 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=3}
    Run #2: ActivityRecord{be92d5b u0 com.wuzy.androidlaunchmodetest/.MainActivity t18326}
    Run #1: ActivityRecord{c62eb86 u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestActivity t18326}
    Run #0: ActivityRecord{eb38b03 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18326}

-----------------------------------------------------------------------------------------

// 3、启动流程
MainActivity -> IntentFlagTestActivity  -> MainActivity -> IntentFlagTestActivity

// 栈内容
Running activities (most recent first):
    TaskRecord{bf65b55 #18326 A=com.wuzy.androidlaunchmodetest U=0 StackId=1 sz=2}
    Run #1: ActivityRecord{c62eb86 u0 com.wuzy.androidlaunchmodetest/.IntentFlagTestActivity t18326}
    Run #0: ActivityRecord{eb38b03 u0 com.wuzy.androidlaunchmodetest/.MainActivity t18326}

FLAG_ACTIVITY_CLEAR_TOP + FLAG_ACTIVITY_SINGLE_TOP 标志位组合情况, standard 模式下的 IntentFlagTestActivity 被复用了, 那么其他启动模式的 Activity 也必然会被复用。(单独使用 FLAG_ACTIVITY_CLEAR_TOP 都会被复用,何况又添加了 FLAG_ACTIVITY_SINGLE_TOP 标志位,通过 Demo 验证也确实如此,就不再给出具体案例了)。

结论

使用 FLAG_ACTIVITY_SINGLE_TOP 和 FLAG_ACTIVITY_CLEAR_TOP 标志位组合,那么不管目标 Activity 是什么启动模式,都会被复用。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 经常混淆,转载的以备今后查看(原链接:https://www.jianshu.com/p/7f1c9fac2af2...
    lkuo阅读 1,020评论 0 1
  • 1.Android 主要包含4种启动模式,下面分别介绍四种启动方式的特点:1)tandard 默认的启动模式,标准...
    SDY_0656阅读 1,119评论 0 1
  • 在介绍 Android 启动模式之前,先介绍两个概念,一个是 task ,另一个是在 Androidmanifes...
    Utopia_Sen阅读 1,377评论 0 6
  • 任务和返回栈 任务是指在执行特定作业时与用户交互的一系列 Activity。 这些 Activity 按照各自的打...
    糖果小猫咪阅读 287评论 0 0
  • 一直对activity的启动模式和种种Flag意识模模糊糊,抽空详细研究了下,这里做一个记录,防止自己再遗忘。 A...
    小屁孩_H阅读 272评论 0 0