孤舟蓑笠翁,独钓寒江雪

Android LaunchMode taskAffinity 与 Intent Flag 详解

taskAffinity

我们可以在 AndroidManifest.xml 中通过 android:taskAffinity 属性为 Activity 指定 taskAffinity。
那么什么是 taskAffinity 呢?
taskAffinity 可以为 Activity 指定归属于那个 Task。
一般情况下,如果应用中的 Activity 都没有特殊的显式指定 taskAffinity,那么它的这个属性就等于 Application 指明的 taskAffinity,如果 Application 也没有指明,那么该 taskAffinity 的值就等于应用的包名。
taskAffinity 可以为任意字符串,但是非空的话必须至少包含一个“.”,否则会编译报错。但是你可以指定taskAffinity为空字符串,这时它就不属于任何 Task。
那么是不是我指定了一个 Activity 的 taskAffinity 值(跟包名不同),运行该 Activity 时,是否就会新开这个 task栈呢?
答案是否定的,一个 Activity 运行时所归属的task,是由 StackId 来决定的,默认是启动它的那个Activity 所在的 task。即使有时我们配置了 taskAffinity,但是它是在特定情况下才会生效的。
taskAffinit 单独使用并不会生效,要想其生效,需要配合其他属性使用,或者在 standard 模式下配合 Intent.FLAG_ACTIVITY_NEW_TASK,或者配合
allowTaskReparenting。或者配合 singleTask 使用。

LaunchMode

standard

标准模式。如果不显式的指定 launchMode,Activity都会按照此种模式启动。这种模式下的 Activity 可以有多个实例,不同任务中可以有不同的 Activity 实例,同一个任务中也可以有多个 Activity 实例。这种模式下启动Activity总是会重新创建Activity,对应调用 onCreate() 方法。
Android L(Android 5.0)前后对这种启动模式的处理方式是不同的:

  • Android L之前:每次以该模式启动的 Activity 都会被压入当前任务的顶部,启动 N 次,在当前任务就会出现 N 个 Activity 的实例,每次Back键就会销毁一个,直到按了 N 次Back键。
  • Android L之后:如果要以该模式启动 Activity 都是来自同一应用,那么还是会像之前一样,压入当前任务的顶部; 如果是来自不同应用,那么将会创建一个新的任务,然后将 Activity 的实例压入新的任务中。Android L做的优化主要是针对多任务的显示。

singleTop

栈顶复用模式。这种模式下栈顶仅有一个 Activity 实例,也就是说不会有多个相同的 Activity 叠加在栈顶。如果当前任务的顶部就是待启动的 Activity 实例,那么并不会再创建一个新的 Activity 实例,而是仅仅调用已有实例的 onNewIntent() 方法,所以对于要以 singleTop 启动的Activity,需要处理 onCreate()onNewIntent() 这两种情况下的启动参数。
但是如果任务中已经有这个 Activity 实例,但是不在栈顶,还是会重新创建一个新的 Activity 实例。

singleTask

栈内复用模式,也是单实例模式。该模式下该 Activity 实例仅有一个 Task 存在。但是该 Task 中可能会有多个 Activity。
系统在该类型的 Task 不存在时创建一个新的 Task,并将该 Activity 放入 Task 底部。具体启动 singleTask 会不会新建一个 Task,则和 TaskAffinity 有关。在我们不设置 android:taskAffinity 的情况下,同一个应用的 Activity 默认具有相同的 TaskAffinity,除非你自己设置了 Activity 的 android:taskAffinity
以 A 启动 B(singleTask)为例,下面我们分集中情况来介绍:

  • A 和 B 的 TaskAffinity 相同,该 Task 里面没有 B:那么就直接在 A 的 Task 里面启动 B。
  • A 和 B 的 TaskAffinity 相同,该 Task 里面存在 B:清除该 Activity 上面的所有对象,把该 Activity 推到前台。
  • A 和 B 的 TaskAffinity 不同,且 B 不存在:则创建一个新的 Task,并将该 Activity 放入 Task 底部。
  • A 和 B 的 TaskAffinity 不同,且 B 存在:在该 Task 中启动该 Activity,并把该 Task 拉回前台,如果该 Activity 上面有其他的对象,则清除该 Activity 上面的所有对象,把该 Activity 推到前台。

也就是说,启动模式为 singleTask 的 Activity 在系统中只会存在一个实例。
如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的 onNewIntent())。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。
但是要注意,系统可能会随时杀掉后台运行的 Activity,如果这一切发生,那么系统就会调用 onCreate() 方法,而不调用 onNewIntent() 方法。,因此,如果有需要在 Activity 启动时处理的方法最好在 onCreate()onNewIntent() 方法中都要调用一下。
我们其实也注意到,Intent Flag 中 有 FLAG_ACTIVITY_NEW_TASK,singleTask 的作用相当于 FLAG_ACTIVITY_CLEAR_TOP + FLAG_ACTIVITY_NEW_TASK。

singleInstance

单实例模式,也是增强型 singleTask 模式。该模式下,系统中只允许有一个存在该 Activity 的 Task 存在,而且该 Task 中只允许有该 Activity 一个实例存在。

  • Activity 不存在:总是新建一个 Task,并且创建一个 Activity。
  • Activity 存在:则会重用该 Activity。

这里可能会有个疑问,如果 A 和 B (singleInstance)的 TaskAffinity 相同,A 启动 B 时的情况是怎么样的呢?我们来做一个测试:
看一下 adb shell dumpsys activity 的打印:
启动 B 前:

1
2
3
4
5
6
7
8
9
Task id #356
TaskRecord{bbe4f0d #356 A=com.example.heqiang.testsomething U=0 sz=2}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.heqiang.testsomething/.MainActivity }
Hist #1: ActivityRecord{eeae154 u0 com.example.heqiang.testsomething/.launchFlag.ActivityA t356}
Intent { cmp=com.example.heqiang.testsomething/.launchFlag.ActivityA }
ProcessRecord{66c150e 15760:com.example.heqiang.testsomething/u0a36}
Hist #0: ActivityRecord{d6950cc u0 com.example.heqiang.testsomething/.MainActivity t356}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.heqiang.testsomething/.MainActivity }
ProcessRecord{66c150e 15760:com.example.heqiang.testsomething/u0a36}

该 Task 里面有 MainActivity 和 A。
A 启动 B:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Task id #361
TaskRecord{378cfdb #361 A=com.example.heqiang.testsomething U=0 sz=1}
Intent { flg=0x10000000 cmp=com.example.heqiang.testsomething/.launchFlag.ActivityB }
Hist #0: ActivityRecord{9e32cdf u0 com.example.heqiang.testsomething/.launchFlag.ActivityB t361}
Intent { flg=0x10000000 cmp=com.example.heqiang.testsomething/.launchFlag.ActivityB }
ProcessRecord{f103a35 16820:com.example.heqiang.testsomething/u0a36}
Task id #360
TaskRecord{99a446c #360 A=com.example.heqiang.testsomething U=0 sz=2}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.heqiang.testsomething/.MainActivity }
Hist #1: ActivityRecord{c51aa5 u0 com.example.heqiang.testsomething/.launchFlag.ActivityA t360}
Intent { cmp=com.example.heqiang.testsomething/.launchFlag.ActivityA }
ProcessRecord{f103a35 16820:com.example.heqiang.testsomething/u0a36}
Hist #0: ActivityRecord{d2364a7 u0 com.example.heqiang.testsomething/.MainActivity t360}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.heqiang.testsomething/.MainActivity }
ProcessRecord{f103a35 16820:com.example.heqiang.testsomething/u0a36}

可以看到,新建了一个 Task 用来管理 ActivityB。印证了上面的总结,Activity 不存在时总是新建一个 Task,并且创建一个 Activity。

区别

  • standard 和 singleTop:这两种模式下 Activity 在系统中可以有多个实例。如果栈顶已经存在待启动 Activity 的实例,singleTop 会利用已有的实例,而 standard 仍然会新建一个。 然而,singleTop 只对当前应用启动有效,对于跨应用启动的情况,singleTop 与 standard 模式没有区别。在跨应用启动这种情况下,Intent 并不会去寻找已有任务的 Activity,而是直接创建一个新的 Activity 实例:在 Android L 之前,将 Activity 实例置于发起者的任务顶,在 Android L 之后,将 Activity 实例置于新任务的根部。
  • singleTask 和 singleInstance 模式的 Activity 在系统中都只有一个实例(当然也就只有一个该 Activity 的Task),但是 singleTask 模式的 Task 中允许有别的 Activity 存在,而 singleInstance 模式的 Task 中只有该 Activity 一个实例,不允许有其他 Activity 存在。

LaunchMode 和 taskAffinity 的关系

standard 模式下指定 taskAffinity

A (MainActivity) 以 standard 模式启动 B(OtherTestActivity),为 B 指定一个不同于 A 的 taskAffinity。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Task id #21330
mFullscreen=true
mBounds=null
mMinWidth=-1
mMinHeight=-1
mLastNonFullscreenBounds=null
TaskRecord{ff958fa #21330 A=com.example.heqiang.testsomething U=0 StackId=1 sz=2}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.heqiang.testsomething/.MainActivity }
Hist #1: ActivityRecord{967b73e u0 com.example.heqiang.testsomething/.commontest.OtherTestActivity t21330}
Intent { cmp=com.example.heqiang.testsomething/.commontest.OtherTestActivity }
ProcessRecord{1a33eab 14060:com.example.heqiang.testsomething/u0a172}
Hist #0: ActivityRecord{daf4dea u0 com.example.heqiang.testsomething/.MainActivity t21330}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.heqiang.testsomething/.MainActivity }
ProcessRecord{1a33eab 14060:com.example.heqiang.testsomething/u0a172}

可以看到,他们仍然在同一个 Task 中,这个 Task 为 A Activity 所在的 Task。
因此在 standard 模式下设置 taskAffinity 没什么作用,正如上面介绍,可以配合 FLAG_ACTIVITY_NEW_TASK 使用。

singleTask 模式下指定 taskAffinity

这种模式下启动和 taskAffinity 的关系上面已经介绍了一些普通的情况,这里不再介绍。
下面来看一个不同的 Activity 指定同一个 taskAffinity 的情况。
我们先来看一下同一个应用中的情况。首先,这两个 Activity 没有指定特殊进程,他们运行在一个进程中。
在 A(MainActivity) 中以 singleTask 启动同一个 taskAffinity (但不同于A)的 B(OtherTestActivity) 和 C(EventActivity) 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Task id #21332
mFullscreen=true
mBounds=null
mMinWidth=-1
mMinHeight=-1
mLastNonFullscreenBounds=null
TaskRecord{a989fd7 #21332 A=com.hq.test U=0 StackId=1 sz=2}
Intent { flg=0x10000000 cmp=com.example.heqiang.testsomething/.commontest.OtherTestActivity }
Hist #1: ActivityRecord{6c49b46 u0 com.example.heqiang.testsomething/.event.EventActivity t21332}
Intent { flg=0x10400000 cmp=com.example.heqiang.testsomething/.event.EventActivity }
ProcessRecord{64a0ee2 22782:com.example.heqiang.testsomething/u0a172}
Hist #0: ActivityRecord{ce7925e u0 com.example.heqiang.testsomething/.commontest.OtherTestActivity t21332}
Intent { flg=0x10000000 cmp=com.example.heqiang.testsomething/.commontest.OtherTestActivity }
ProcessRecord{64a0ee2 22782:com.example.heqiang.testsomething/u0a172}
Task id #21331
mFullscreen=true
mBounds=null
mMinWidth=-1
mMinHeight=-1
mLastNonFullscreenBounds=null
TaskRecord{aafbad #21331 A=com.example.heqiang.testsomething U=0 StackId=1 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.heqiang.testsomething/.MainActivity }
Hist #0: ActivityRecord{f944c08 u0 com.example.heqiang.testsomething/.MainActivity t21331}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.heqiang.testsomething/.MainActivity }
ProcessRecord{64a0ee2 22782:com.example.heqiang.testsomething/u0a172}

可以看到,这种情况下,B 和 C 在同一个 Task中,而且在同一个进程中。
不在同一个进程的情况这里就不再测试了, B 和 C 这时候仍在 在同一个 Task 中。也就是说 Task 和 进程没有联系。

下面来说明一种情况,就是 A 应用和 B 应用依赖了SDK包,他们以 singleTask 模式启动 SDK 中的同一个 Activity C,这又该什么情况呢?
其实这种情况只要你理解了下面的事实,那么 LaunchMode 、taskAffinity 以及 Task 的关系就很容易理解了。
也就是虽然 SDK 中的 C 从代码层面上讲是同一个,但是对于A 应用和 B 应用来说,调用的确实两个不同的 Activity ,因为它们的包名不同,比如:

  • com.hq.test.sdkdemo/com.hq.sdk.TestActivity
  • com.example.heqiang.testsomething/com.hq.sdk.TestActivity

可以下面的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Task id #21313
mFullscreen=true
mBounds=null
mMinWidth=-1
mMinHeight=-1
mLastNonFullscreenBounds=null
TaskRecord{6cf314a #21313 A=com.hq.test U=0 StackId=1 sz=2}
Intent { flg=0x10000000 cmp=com.example.heqiang.testsomething/com.hq.sdk.TestActivity }
Hist #1: ActivityRecord{88936eb u0 com.hq.test.sdkdemo/com.hq.sdk.TestActivity t21313}
Intent { flg=0x10400000 cmp=com.hq.test.sdkdemo/com.hq.sdk.TestActivity }
ProcessRecord{7571816 5028:com.hq.test.sdkdemo/u0a137}
Hist #0: ActivityRecord{dc4f387 u0 com.example.heqiang.testsomething/com.hq.sdk.TestActivity t21313}
Intent { flg=0x10000000 cmp=com.example.heqiang.testsomething/com.hq.sdk.TestActivity }
ProcessRecord{702597 3847:com.example.heqiang.testsomething/u0a172}
Task id #21315
mFullscreen=true
mBounds=null
mMinWidth=-1
mMinHeight=-1
mLastNonFullscreenBounds=null
TaskRecord{751d1d8 #21315 A=com.hq.test.sdkdemo U=0 StackId=1 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.hq.test.sdkdemo/.MainActivity }
Hist #0: ActivityRecord{7b3c6a6 u0 com.hq.test.sdkdemo/.MainActivity t21315}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.hq.test.sdkdemo/.MainActivity }
ProcessRecord{7571816 5028:com.hq.test.sdkdemo/u0a137}
Task id #21312
mFullscreen=true
mBounds=null
mMinWidth=-1
mMinHeight=-1
mLastNonFullscreenBounds=null
TaskRecord{d65931 #21312 A=com.example.heqiang.testsomething U=0 StackId=1 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.heqiang.testsomething/.MainActivity }
Hist #0: ActivityRecord{85b37c0 u0 com.example.heqiang.testsomething/.MainActivity t21312}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.heqiang.testsomething/.MainActivity }
ProcessRecord{702597 3847:com.example.heqiang.testsomething/u0a172}

在 com.hq.test Task中,有两个 TestActivity,他们属于不同进程。

Intent Flag

FLAG_ACTIVITY_NEW_TASK

设置 FLAG_ACTIVITY_NEW_TASK 标志位时,当有 task 运行了你要运行的 activity,这个task会到前台并,并且这个activity会回调 onNewIntent(),而不是创建新的。 如果没有就会去创建新的 activity。
设置 FLAG_ACTIVITY_NEW_TASK 标志位是,具体是新建 stask 启动还是在当前 stask 中启动 activity,就和 activity 的 taskAffinity 有关系了。
FLAG_ACTIVITY_NEW_TASK 只会去关心该 Activity 的 Task 的个数,如果不存在就新建,存在就直接推到前台。而不去关心 Activity 的个数(和启动模式有关),也就是说该 Task 中可以有多个 Activity 存在,这个要和 singleTask 做区别。
下来来介绍一下需要注意的几个点:
第一种情况:OtherTestActivity(默认 taskAffinity),ActivityA(设置新的taskAffinity)、ActivityB(默认 taskAffinity)。OtherTestActivity 启动ActivityA,ActivityA启动ActivityB时都加上 FLAG_ACTIVITY_NEW_TASK。
来看一下栈的情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
Stack #1571: type=standard mode=fullscreen
isSleeping=false
mBounds=Rect(0, 0 - 0, 0)
Task id #3345
mBounds=Rect(0, 0 - 0, 0)
mMinWidth=-1
mMinHeight=-1
mLastNonFullscreenBounds=null
* TaskRecord{a4848a0 #3345 A=com.example.heqiang.testsomething U=0 StackId=1571 sz=3}
userId=0 effectiveUid=u0a37 mCallingUid=u0a33 mUserSetupComplete=true mCallingPackage=com.android.systemui
affinity=com.example.heqiang.testsomething
intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.heqiang.testsomething/.MainActivity}
realActivity=com.example.heqiang.testsomething/.MainActivity
autoRemoveRecents=false isPersistable=true numFullscreen=3 activityType=1
rootWasReset=true mNeverRelinquishIdentity=true mReuseTask=false mLockTaskAuth=LOCK_TASK_AUTH_PINNABLE
Activities=[ActivityRecord{1111663 u0 com.example.heqiang.testsomething/.MainActivity t3345}, ActivityRecord{df6006f u0 com.example.heqiang.testsomething/.commontest.OtherTestActivity t3345}, ActivityRecord{bfaaa40 u0 com.example.heqiang.testsomething/.launchFlag.ActivityB t3345}]
askedCompatMode=false inRecents=true isAvailable=true mLaunchedFromMultiWindow=false
mRootProcess=ProcessRecord{2a7dc59 26550:com.example.heqiang.testsomething/u0a37}
stackId=1571
hasBeenVisible=true mResizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION mSupportsPictureInPicture=false isResizeable=true lastActiveTime=2918370622 (inactive for 4s)
* Hist #2: ActivityRecord{bfaaa40 u0 com.example.heqiang.testsomething/.launchFlag.ActivityB t3345}
packageName=com.example.heqiang.testsomething processName=com.example.heqiang.testsomething
launchedFromUid=10037 launchedFromPackage=com.example.heqiang.testsomething userId=0
app=ProcessRecord{2a7dc59 26550:com.example.heqiang.testsomething/u0a37}
Intent { flg=0x10400000 cmp=com.example.heqiang.testsomething/.launchFlag.ActivityB }
frontOfTask=false task=TaskRecord{a4848a0 #3345 A=com.example.heqiang.testsomething U=0 StackId=1571 sz=3}
taskAffinity=com.example.heqiang.testsomething
realActivity=com.example.heqiang.testsomething/.launchFlag.ActivityB
baseDir=/data/app/com.example.heqiang.testsomething-zzSgCbKisHaYs61sWCNFHw==/base.apk
dataDir=/data/user/0/com.example.heqiang.testsomething
stateNotNeeded=false componentSpecified=true mActivityType=standard
compat={480dpi} labelRes=0x7f0f0020 icon=0x7f0d0000 theme=0x7f1000d2
mLastReportedConfigurations:
......
* Hist #1: ActivityRecord{df6006f u0 com.example.heqiang.testsomething/.commontest.OtherTestActivity t3345}
packageName=com.example.heqiang.testsomething processName=com.example.heqiang.testsomething
launchedFromUid=10037 launchedFromPackage=com.example.heqiang.testsomething userId=0
app=ProcessRecord{2a7dc59 26550:com.example.heqiang.testsomething/u0a37}
Intent { cmp=com.example.heqiang.testsomething/.commontest.OtherTestActivity (has extras) }
frontOfTask=false task=TaskRecord{a4848a0 #3345 A=com.example.heqiang.testsomething U=0 StackId=1571 sz=3}
taskAffinity=com.hq.test.task
realActivity=com.example.heqiang.testsomething/.commontest.OtherTestActivity
baseDir=/data/app/com.example.heqiang.testsomething-zzSgCbKisHaYs61sWCNFHw==/base.apk
dataDir=/data/user/0/com.example.heqiang.testsomething
stateNotNeeded=false componentSpecified=true mActivityType=standard
compat={480dpi} labelRes=0x7f0f0020 icon=0x7f0d0000 theme=0x7f1000d2
mLastReportedConfigurations:
......
* Hist #0: ActivityRecord{1111663 u0 com.example.heqiang.testsomething/.MainActivity t3345}
packageName=com.example.heqiang.testsomething processName=com.example.heqiang.testsomething
launchedFromUid=10033 launchedFromPackage=com.android.systemui userId=0
app=ProcessRecord{2a7dc59 26550:com.example.heqiang.testsomething/u0a37}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.heqiang.testsomething/.MainActivity bnds=[540,1235][792,1510] (has extras) }
frontOfTask=true task=TaskRecord{a4848a0 #3345 A=com.example.heqiang.testsomething U=0 StackId=1571 sz=3}
taskAffinity=com.example.heqiang.testsomething
realActivity=com.example.heqiang.testsomething/.MainActivity
baseDir=/data/app/com.example.heqiang.testsomething-zzSgCbKisHaYs61sWCNFHw==/base.apk
dataDir=/data/user/0/com.example.heqiang.testsomething
stateNotNeeded=false componentSpecified=true mActivityType=standard
compat={480dpi} labelRes=0x7f0f0020 icon=0x7f0d0000 theme=0x7f100006
mLastReportedConfigurations:
......

Running activities (most recent first):
TaskRecord{a4848a0 #3345 A=com.example.heqiang.testsomething U=0 StackId=1571 sz=3}
Run #2: ActivityRecord{bfaaa40 u0 com.example.heqiang.testsomething/.launchFlag.ActivityB t3345}
Run #1: ActivityRecord{df6006f u0 com.example.heqiang.testsomething/.commontest.OtherTestActivity t3345}
Run #0: ActivityRecord{1111663 u0 com.example.heqiang.testsomething/.MainActivity t3345}

mResumedActivity: ActivityRecord{bfaaa40 u0 com.example.heqiang.testsomething/.launchFlag.ActivityB t3345}

Stack #1572: type=standard mode=fullscreen
isSleeping=false
mBounds=Rect(0, 0 - 0, 0)

Task id #3346
mBounds=Rect(0, 0 - 0, 0)
mMinWidth=-1
mMinHeight=-1
mLastNonFullscreenBounds=null
* TaskRecord{c72201e #3346 A=com.example.heqiang.testsomething:ActivityA U=0 StackId=1572 sz=1}
userId=0 effectiveUid=u0a37 mCallingUid=u0a37 mUserSetupComplete=true mCallingPackage=com.example.heqiang.testsomething
affinity=com.example.heqiang.testsomething:ActivityA
intent={act=Tests flg=0x10000000 cmp=com.example.heqiang.testsomething/.launchFlag.ActivityA}
realActivity=com.example.heqiang.testsomething/.launchFlag.ActivityA
autoRemoveRecents=false isPersistable=true numFullscreen=1 activityType=1
rootWasReset=false mNeverRelinquishIdentity=true mReuseTask=false mLockTaskAuth=LOCK_TASK_AUTH_PINNABLE
Activities=[ActivityRecord{12a072d u0 com.example.heqiang.testsomething/.launchFlag.ActivityA t3346}]
askedCompatMode=false inRecents=true isAvailable=true mLaunchedFromMultiWindow=false
mRootProcess=ProcessRecord{2a7dc59 26550:com.example.heqiang.testsomething/u0a37}
stackId=1572
hasBeenVisible=true mResizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION mSupportsPictureInPicture=false isResizeable=true lastActiveTime=2918370481 (inactive for 4s)
* Hist #0: ActivityRecord{12a072d u0 com.example.heqiang.testsomething/.launchFlag.ActivityA t3346}
packageName=com.example.heqiang.testsomething processName=com.example.heqiang.testsomething
launchedFromUid=10037 launchedFromPackage=com.example.heqiang.testsomething userId=0
app=ProcessRecord{2a7dc59 26550:com.example.heqiang.testsomething/u0a37}
Intent { act=Tests flg=0x10000000 cmp=com.example.heqiang.testsomething/.launchFlag.ActivityA }
frontOfTask=true task=TaskRecord{c72201e #3346 A=com.example.heqiang.testsomething:ActivityA U=0 StackId=1572 sz=1}
taskAffinity=com.example.heqiang.testsomething:ActivityA
realActivity=com.example.heqiang.testsomething/.launchFlag.ActivityA
baseDir=/data/app/com.example.heqiang.testsomething-zzSgCbKisHaYs61sWCNFHw==/base.apk
dataDir=/data/user/0/com.example.heqiang.testsomething
stateNotNeeded=false componentSpecified=true mActivityType=standard
compat={480dpi} labelRes=0x7f0f0020 icon=0x7f0d0000 theme=0x7f1000d2
mLastReportedConfigurations:
......

Running activities (most recent first):
TaskRecord{c72201e #3346 A=com.example.heqiang.testsomething:ActivityA U=0 StackId=1572 sz=1}
Run #0: ActivityRecord{12a072d u0 com.example.heqiang.testsomething/.launchFlag.ActivityA t3346}

mLastPausedActivity: ActivityRecord{12a072d u0 com.example.heqiang.testsomething/.launchFlag.ActivityA t3346}

可以看到,OtherTestActivity 启动ActivityA时,在新的栈上创建 ActivityA,ActivityA启动ActivityB时会在 OtherTestActivity 所在的栈中添加 ActivityB。

再看另外一种情况:

OtherTestActivity(默认 taskAffinity),ActivityA(设置新的taskAffinity)、ActivityB(默认 taskAffinity)。OtherTestActivity 启动ActivityA时加上 FLAG_ACTIVITY_NEW_TASK,ActivityA启动ActivityB时不加。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
Stack #1578: type=standard mode=fullscreen
isSleeping=false
mBounds=Rect(0, 0 - 0, 0)
Task id #3352
mBounds=Rect(0, 0 - 0, 0)
mMinWidth=-1
mMinHeight=-1
mLastNonFullscreenBounds=null
* TaskRecord{b632e5f #3352 A=com.example.heqiang.testsomething:ActivityA U=0 StackId=1578 sz=2}
userId=0 effectiveUid=u0a37 mCallingUid=u0a37 mUserSetupComplete=true mCallingPackage=com.example.heqiang.testsomething
affinity=com.example.heqiang.testsomething:ActivityA
intent={act=Tests flg=0x10000000 cmp=com.example.heqiang.testsomething/.launchFlag.ActivityA}
realActivity=com.example.heqiang.testsomething/.launchFlag.ActivityA
autoRemoveRecents=false isPersistable=true numFullscreen=2 activityType=1
rootWasReset=false mNeverRelinquishIdentity=true mReuseTask=false mLockTaskAuth=LOCK_TASK_AUTH_PINNABLE
Activities=[ActivityRecord{83b2f2 u0 com.example.heqiang.testsomething/.launchFlag.ActivityA t3352}, ActivityRecord{66d3402 u0 com.example.heqiang.testsomething/.launchFlag.ActivityB t3352}]
askedCompatMode=false inRecents=true isAvailable=true mLaunchedFromMultiWindow=false
mRootProcess=ProcessRecord{dd5e0ac 27117:com.example.heqiang.testsomething/u0a37}
stackId=1578
hasBeenVisible=true mResizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION mSupportsPictureInPicture=false isResizeable=true lastActiveTime=2919082443 (inactive for 1s)
* Hist #1: ActivityRecord{66d3402 u0 com.example.heqiang.testsomething/.launchFlag.ActivityB t3352}
packageName=com.example.heqiang.testsomething processName=com.example.heqiang.testsomething
launchedFromUid=10037 launchedFromPackage=com.example.heqiang.testsomething userId=0
app=ProcessRecord{dd5e0ac 27117:com.example.heqiang.testsomething/u0a37}
Intent { cmp=com.example.heqiang.testsomething/.launchFlag.ActivityB }
frontOfTask=false task=TaskRecord{b632e5f #3352 A=com.example.heqiang.testsomething:ActivityA U=0 StackId=1578 sz=2}
taskAffinity=com.example.heqiang.testsomething
realActivity=com.example.heqiang.testsomething/.launchFlag.ActivityB
baseDir=/data/app/com.example.heqiang.testsomething-dhnrkpKFABfE8N6-eIbVjA==/base.apk
dataDir=/data/user/0/com.example.heqiang.testsomething
stateNotNeeded=false componentSpecified=true mActivityType=standard
compat={480dpi} labelRes=0x7f0f0020 icon=0x7f0d0000 theme=0x7f1000d2
mLastReportedConfigurations:
......
* Hist #0: ActivityRecord{83b2f2 u0 com.example.heqiang.testsomething/.launchFlag.ActivityA t3352}
packageName=com.example.heqiang.testsomething processName=com.example.heqiang.testsomething
launchedFromUid=10037 launchedFromPackage=com.example.heqiang.testsomething userId=0
app=ProcessRecord{dd5e0ac 27117:com.example.heqiang.testsomething/u0a37}
Intent { act=Tests flg=0x10000000 cmp=com.example.heqiang.testsomething/.launchFlag.ActivityA }
frontOfTask=true task=TaskRecord{b632e5f #3352 A=com.example.heqiang.testsomething:ActivityA U=0 StackId=1578 sz=2}
taskAffinity=com.example.heqiang.testsomething:ActivityA
realActivity=com.example.heqiang.testsomething/.launchFlag.ActivityA
baseDir=/data/app/com.example.heqiang.testsomething-dhnrkpKFABfE8N6-eIbVjA==/base.apk
dataDir=/data/user/0/com.example.heqiang.testsomething
stateNotNeeded=false componentSpecified=true mActivityType=standard
compat={480dpi} labelRes=0x7f0f0020 icon=0x7f0d0000 theme=0x7f1000d2
mLastReportedConfigurations:
......

Running activities (most recent first):
TaskRecord{b632e5f #3352 A=com.example.heqiang.testsomething:ActivityA U=0 StackId=1578 sz=2}
Run #1: ActivityRecord{66d3402 u0 com.example.heqiang.testsomething/.launchFlag.ActivityB t3352}
Run #0: ActivityRecord{83b2f2 u0 com.example.heqiang.testsomething/.launchFlag.ActivityA t3352}

mResumedActivity: ActivityRecord{66d3402 u0 com.example.heqiang.testsomething/.launchFlag.ActivityB t3352}
mLastPausedActivity: ActivityRecord{83b2f2 u0 com.example.heqiang.testsomething/.launchFlag.ActivityA t3352}

Stack #1577: type=standard mode=fullscreen
isSleeping=false
mBounds=Rect(0, 0 - 0, 0)

Task id #3351
mBounds=Rect(0, 0 - 0, 0)
mMinWidth=-1
mMinHeight=-1
mLastNonFullscreenBounds=null
* TaskRecord{f8d4175 #3351 A=com.example.heqiang.testsomething U=0 StackId=1577 sz=2}
userId=0 effectiveUid=u0a37 mCallingUid=u0a33 mUserSetupComplete=true mCallingPackage=com.android.systemui
affinity=com.example.heqiang.testsomething
intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.heqiang.testsomething/.MainActivity}
realActivity=com.example.heqiang.testsomething/.MainActivity
autoRemoveRecents=false isPersistable=true numFullscreen=2 activityType=1
rootWasReset=true mNeverRelinquishIdentity=true mReuseTask=false mLockTaskAuth=LOCK_TASK_AUTH_PINNABLE
Activities=[ActivityRecord{731edb3 u0 com.example.heqiang.testsomething/.MainActivity t3351}, ActivityRecord{75b69db u0 com.example.heqiang.testsomething/.commontest.OtherTestActivity t3351}]
askedCompatMode=false inRecents=true isAvailable=true mLaunchedFromMultiWindow=false
mRootProcess=ProcessRecord{dd5e0ac 27117:com.example.heqiang.testsomething/u0a37}
stackId=1577
hasBeenVisible=true mResizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION mSupportsPictureInPicture=false isResizeable=true lastActiveTime=2919081400 (inactive for 2s)
* Hist #1: ActivityRecord{75b69db u0 com.example.heqiang.testsomething/.commontest.OtherTestActivity t3351}
packageName=com.example.heqiang.testsomething processName=com.example.heqiang.testsomething
launchedFromUid=10037 launchedFromPackage=com.example.heqiang.testsomething userId=0
app=ProcessRecord{dd5e0ac 27117:com.example.heqiang.testsomething/u0a37}
Intent { cmp=com.example.heqiang.testsomething/.commontest.OtherTestActivity (has extras) }
frontOfTask=false task=TaskRecord{f8d4175 #3351 A=com.example.heqiang.testsomething U=0 StackId=1577 sz=2}
taskAffinity=com.hq.test.task
realActivity=com.example.heqiang.testsomething/.commontest.OtherTestActivity
baseDir=/data/app/com.example.heqiang.testsomething-dhnrkpKFABfE8N6-eIbVjA==/base.apk
dataDir=/data/user/0/com.example.heqiang.testsomething
stateNotNeeded=false componentSpecified=true mActivityType=standard
compat={480dpi} labelRes=0x7f0f0020 icon=0x7f0d0000 theme=0x7f1000d2
mLastReportedConfigurations:
......
* Hist #0: ActivityRecord{731edb3 u0 com.example.heqiang.testsomething/.MainActivity t3351}
packageName=com.example.heqiang.testsomething processName=com.example.heqiang.testsomething
launchedFromUid=10033 launchedFromPackage=com.android.systemui userId=0
app=ProcessRecord{dd5e0ac 27117:com.example.heqiang.testsomething/u0a37}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.heqiang.testsomething/.MainActivity bnds=[540,1235][792,1510] (has extras) }
frontOfTask=true task=TaskRecord{f8d4175 #3351 A=com.example.heqiang.testsomething U=0 StackId=1577 sz=2}
taskAffinity=com.example.heqiang.testsomething
realActivity=com.example.heqiang.testsomething/.MainActivity
baseDir=/data/app/com.example.heqiang.testsomething-dhnrkpKFABfE8N6-eIbVjA==/base.apk
dataDir=/data/user/0/com.example.heqiang.testsomething
stateNotNeeded=false componentSpecified=true mActivityType=standard
compat={480dpi} labelRes=0x7f0f0020 icon=0x7f0d0000 theme=0x7f100006
mLastReportedConfigurations:
......

Running activities (most recent first):
TaskRecord{f8d4175 #3351 A=com.example.heqiang.testsomething U=0 StackId=1577 sz=2}
Run #1: ActivityRecord{75b69db u0 com.example.heqiang.testsomething/.commontest.OtherTestActivity t3351}
Run #0: ActivityRecord{731edb3 u0 com.example.heqiang.testsomething/.MainActivity t3351}

mLastPausedActivity: ActivityRecord{75b69db u0 com.example.heqiang.testsomething/.commontest.OtherTestActivity t3351}

可以看到,OtherTestActivity 启动ActivityA时,在新的栈上创建 ActivityA,ActivityA启动 ActivityB时会在 ActivityA 所在的栈中添加 ActivityB。
这是我们进行下面一步测试,从多任务中打开 OtherTestActivity,从新点击按钮启动 ActivityA:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
Stack #1578: type=standard mode=fullscreen
isSleeping=false
mBounds=Rect(0, 0 - 0, 0)
Task id #3352
mBounds=Rect(0, 0 - 0, 0)
mMinWidth=-1
mMinHeight=-1
mLastNonFullscreenBounds=null
* TaskRecord{b632e5f #3352 A=com.example.heqiang.testsomething:ActivityA U=0 StackId=1578 sz=2}
userId=0 effectiveUid=u0a37 mCallingUid=u0a37 mUserSetupComplete=true mCallingPackage=com.example.heqiang.testsomething
affinity=com.example.heqiang.testsomething:ActivityA
intent={act=Tests flg=0x10000000 cmp=com.example.heqiang.testsomething/.launchFlag.ActivityA}
realActivity=com.example.heqiang.testsomething/.launchFlag.ActivityA
autoRemoveRecents=false isPersistable=true numFullscreen=2 activityType=1
rootWasReset=false mNeverRelinquishIdentity=true mReuseTask=false mLockTaskAuth=LOCK_TASK_AUTH_PINNABLE
Activities=[ActivityRecord{83b2f2 u0 com.example.heqiang.testsomething/.launchFlag.ActivityA t3352}, ActivityRecord{66d3402 u0 com.example.heqiang.testsomething/.launchFlag.ActivityB t3352}]
askedCompatMode=false inRecents=true isAvailable=true mLaunchedFromMultiWindow=false
mRootProcess=ProcessRecord{dd5e0ac 27117:com.example.heqiang.testsomething/u0a37}
stackId=1578
hasBeenVisible=true mResizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION mSupportsPictureInPicture=false isResizeable=true lastActiveTime=2919312473 (inactive for 2s)
* Hist #1: ActivityRecord{66d3402 u0 com.example.heqiang.testsomething/.launchFlag.ActivityB t3352}
packageName=com.example.heqiang.testsomething processName=com.example.heqiang.testsomething
launchedFromUid=10037 launchedFromPackage=com.example.heqiang.testsomething userId=0
app=ProcessRecord{dd5e0ac 27117:com.example.heqiang.testsomething/u0a37}
Intent { cmp=com.example.heqiang.testsomething/.launchFlag.ActivityB }
frontOfTask=false task=TaskRecord{b632e5f #3352 A=com.example.heqiang.testsomething:ActivityA U=0 StackId=1578 sz=2}
taskAffinity=com.example.heqiang.testsomething
realActivity=com.example.heqiang.testsomething/.launchFlag.ActivityB
baseDir=/data/app/com.example.heqiang.testsomething-dhnrkpKFABfE8N6-eIbVjA==/base.apk
dataDir=/data/user/0/com.example.heqiang.testsomething
stateNotNeeded=false componentSpecified=true mActivityType=standard
compat={480dpi} labelRes=0x7f0f0020 icon=0x7f0d0000 theme=0x7f1000d2
mLastReportedConfigurations:
......
* Hist #0: ActivityRecord{83b2f2 u0 com.example.heqiang.testsomething/.launchFlag.ActivityA t3352}
packageName=com.example.heqiang.testsomething processName=com.example.heqiang.testsomething
launchedFromUid=10037 launchedFromPackage=com.example.heqiang.testsomething userId=0
app=ProcessRecord{dd5e0ac 27117:com.example.heqiang.testsomething/u0a37}
Intent { act=Tests flg=0x10000000 cmp=com.example.heqiang.testsomething/.launchFlag.ActivityA }
frontOfTask=true task=TaskRecord{b632e5f #3352 A=com.example.heqiang.testsomething:ActivityA U=0 StackId=1578 sz=2}
taskAffinity=com.example.heqiang.testsomething:ActivityA
realActivity=com.example.heqiang.testsomething/.launchFlag.ActivityA
baseDir=/data/app/com.example.heqiang.testsomething-dhnrkpKFABfE8N6-eIbVjA==/base.apk
dataDir=/data/user/0/com.example.heqiang.testsomething
stateNotNeeded=false componentSpecified=true mActivityType=standard
compat={480dpi} labelRes=0x7f0f0020 icon=0x7f0d0000 theme=0x7f1000d2
mLastReportedConfigurations:
......

Running activities (most recent first):
TaskRecord{b632e5f #3352 A=com.example.heqiang.testsomething:ActivityA U=0 StackId=1578 sz=2}
Run #1: ActivityRecord{66d3402 u0 com.example.heqiang.testsomething/.launchFlag.ActivityB t3352}
Run #0: ActivityRecord{83b2f2 u0 com.example.heqiang.testsomething/.launchFlag.ActivityA t3352}

mResumedActivity: ActivityRecord{66d3402 u0 com.example.heqiang.testsomething/.launchFlag.ActivityB t3352}

Stack #1577: type=standard mode=fullscreen
isSleeping=false
mBounds=Rect(0, 0 - 0, 0)

Task id #3351
mBounds=Rect(0, 0 - 0, 0)
mMinWidth=-1
mMinHeight=-1
mLastNonFullscreenBounds=null
* TaskRecord{f8d4175 #3351 A=com.example.heqiang.testsomething U=0 StackId=1577 sz=2}
userId=0 effectiveUid=u0a37 mCallingUid=u0a33 mUserSetupComplete=true mCallingPackage=com.android.systemui
affinity=com.example.heqiang.testsomething
intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.heqiang.testsomething/.MainActivity}
realActivity=com.example.heqiang.testsomething/.MainActivity
autoRemoveRecents=false isPersistable=true numFullscreen=2 activityType=1
rootWasReset=true mNeverRelinquishIdentity=true mReuseTask=false mLockTaskAuth=LOCK_TASK_AUTH_PINNABLE
Activities=[ActivityRecord{731edb3 u0 com.example.heqiang.testsomething/.MainActivity t3351}, ActivityRecord{75b69db u0 com.example.heqiang.testsomething/.commontest.OtherTestActivity t3351}]
askedCompatMode=false inRecents=true isAvailable=true mLaunchedFromMultiWindow=false
mRootProcess=ProcessRecord{dd5e0ac 27117:com.example.heqiang.testsomething/u0a37}
stackId=1577
hasBeenVisible=true mResizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION mSupportsPictureInPicture=false isResizeable=true lastActiveTime=2919312337 (inactive for 3s)
* Hist #1: ActivityRecord{75b69db u0 com.example.heqiang.testsomething/.commontest.OtherTestActivity t3351}
packageName=com.example.heqiang.testsomething processName=com.example.heqiang.testsomething
launchedFromUid=10037 launchedFromPackage=com.example.heqiang.testsomething userId=0
app=ProcessRecord{dd5e0ac 27117:com.example.heqiang.testsomething/u0a37}
Intent { cmp=com.example.heqiang.testsomething/.commontest.OtherTestActivity (has extras) }
frontOfTask=false task=TaskRecord{f8d4175 #3351 A=com.example.heqiang.testsomething U=0 StackId=1577 sz=2}
taskAffinity=com.hq.test.task
realActivity=com.example.heqiang.testsomething/.commontest.OtherTestActivity
baseDir=/data/app/com.example.heqiang.testsomething-dhnrkpKFABfE8N6-eIbVjA==/base.apk
dataDir=/data/user/0/com.example.heqiang.testsomething
stateNotNeeded=false componentSpecified=true mActivityType=standard
compat={480dpi} labelRes=0x7f0f0020 icon=0x7f0d0000 theme=0x7f1000d2
mLastReportedConfigurations:
......
* Hist #0: ActivityRecord{731edb3 u0 com.example.heqiang.testsomething/.MainActivity t3351}
packageName=com.example.heqiang.testsomething processName=com.example.heqiang.testsomething
launchedFromUid=10033 launchedFromPackage=com.android.systemui userId=0
app=ProcessRecord{dd5e0ac 27117:com.example.heqiang.testsomething/u0a37}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.heqiang.testsomething/.MainActivity bnds=[540,1235][792,1510] (has extras) }
frontOfTask=true task=TaskRecord{f8d4175 #3351 A=com.example.heqiang.testsomething U=0 StackId=1577 sz=2}
taskAffinity=com.example.heqiang.testsomething
realActivity=com.example.heqiang.testsomething/.MainActivity
baseDir=/data/app/com.example.heqiang.testsomething-dhnrkpKFABfE8N6-eIbVjA==/base.apk
dataDir=/data/user/0/com.example.heqiang.testsomething
stateNotNeeded=false componentSpecified=true mActivityType=standard
compat={480dpi} labelRes=0x7f0f0020 icon=0x7f0d0000 theme=0x7f100006
mLastReportedConfigurations:
......

Running activities (most recent first):
TaskRecord{f8d4175 #3351 A=com.example.heqiang.testsomething U=0 StackId=1577 sz=2}
Run #1: ActivityRecord{75b69db u0 com.example.heqiang.testsomething/.commontest.OtherTestActivity t3351}
Run #0: ActivityRecord{731edb3 u0 com.example.heqiang.testsomething/.MainActivity t3351}

mLastPausedActivity: ActivityRecord{75b69db u0 com.example.heqiang.testsomething/.commontest.OtherTestActivity t3351}

可以看到,这时并没有新建 ActivityA,而是把 ActivityA 和 ActivityB所在的栈推到了前台,ActivityB 仍然在 ActivityA 上面。
基于此再做一个测试:从ActivityB再启动ActivityA。
发现,在这种情况下,栈的情况都没有变化,和上面的情况是一样的。因为当前栈本来就在前台。要注意,从两个 activity 情况下启动同一个activiyt只是推栈到前台,必须要保证启动的 Intent 一样才行。

FLAG_ACTIVITY_CLEAR_TOP

启动模式不同,具体操作也不一样。但是都会清除该 Activity 上面的所有对象。
standard 模式:系统收到新的 Intent 时,如果 Task 中存在该 Activity 则弹出 Activity 和 Activity 上面的所有对象,并重新初始化一个新的 Activity 对象放入栈顶,以处理 Intent 请求。因为 standard 总是初始化新的 Activity 来处理 Intent请求。
其他模式:则会将 Activity 上面的对象弹出,使该 Activity 在栈顶部,以处理 Intent请求。

FLAG_ACTIVITY_CLEAR_TASK

启动 Activity 时如果加入了这个标志,那么如果存放该 Activity 的 Task 已经存在,会先把该 Task 里面所有的 Activity 清空,然后再启动该 Activity。那么该 Activity 就成了该 Task 里面唯一的一个 Activity。
应用场景:如果在同一 Task 里面 A 启动 B,B 启动 C,但是在 C 里面后退的话会默认返回 B,然后再返回 A,如果不想返回 B 和 A,那么就可以用该 Flag,启动 C 时把 A 和 B 清除掉,比如在登陆界面跳转到到主界面。从主界面后退肯定不想返回登陆界面的。

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

通过这个 Flag 启动的 Activity 将不会添加到最近使用应用列表中,我们从任务管理器中无法找到这个 Activity。

FLAG_ACTIVITY_NO_HISTORY

通过这个 Flag 启动的 Activity 一旦退出后,就不会存在栈中。比如 A 添加这个 Flag 启动 B,B启动 C,这是栈中就只有 A、C。

FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY

当从手机任务管理器启动的Activity Intent 的 Flag 会带有这个属性,我们可以用它来区分是否从任务管理器里面启动的。

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

只有当新启动一个任务栈或任务栈被切换到前台时才有用,也就意味着该标记只会加在任务栈的根 Activity 上,用这个标记来表明需要重置任务栈的状态。
一般与FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET结合使用。

FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET

设置此标签相当于在任务栈中标记一个位置,当任务栈被重置时,从该标记位置到栈顶的 Activity 全部被清除。所谓的任务栈重置,是指当程序从后台进入前台时(通常是用户从主屏重新点击启动图标,或者从 recent apps 重新进入程序),如果栈顶的 Activity 设置了 FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 标记,那么从设置 FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET 标记到栈顶的 Activity 会全部被清除掉。
举例:该标签可用于这种情况,用户在浏览邮件时,通过另外一个 Activity 来打开图片附件,这时用户可能会按 Home 键返回主屏,进行其它操作,一段时间后重新点击邮件的启动图标进入程序,这时应该显示邮件的内容而不是图片,因为用户可能是很长时间后返回邮件 App 的,也许已经忘记之前的操作,如果用户打开邮件后看到的是一张图片,可能会觉得很困惑。而设置 FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET 标记后,用户再次打开程序时,任务栈就会把图片 Activity 清除掉,显示邮件内容。

LaunchMode 与 StartActivityForResult 的关系