Android 中的 Activity 有几种比较重要的启动模式,StandardSingleTopSingleTaskSingleInstance , 每一种启动模式有不同的使用场景, 网上也有许多分析这个的文章, 这里我以 Demo 的模式, 从 Activity 栈的角度来展示不同启动模式下的 Activity 的行为.
Activity 栈是一个先进后出的数据结构, 各位可以关注在每一步操作之后, 栈内容那一栏 , 可以更好地帮助理解不同的启动模式.
Demo 比较简单, 我也放到了 Github 上 , https://github.com/Gracker/AndroidLaunchModeTest , 有兴趣的可以自己跑一下 , 看看结果 , 只需要修改 StandardActivity 里面的跳转 Activity 就可以了.
Standard 标准模式
android:launchMode="standard"
最基本的模式,每次启动都会创建一个新的 Activity
// 1. 启动 Activity
MainActivity
//栈内容
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 2. 启动 StandardActivity
MainActivity -> StandardActivity
//栈内容
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 3. 启动 StandardActivity
MainActivity -> StandardActivity -> StandardActivity
//栈内容
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
SingleTop 栈顶复用模式
android:launchMode="singleTop"
如果当前 Activity 已经在栈顶,那么其 onNewIntent 会被调用;否则会重新创建 Activity
测试1 : SingleTopActivity 不在栈顶
// 1. 启动 MainActivity
MainActivity
//栈内容
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 2. 启动 StandardActivity
MainActivity -> StandardActivity
//栈内容
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 3. 启动 SingleTopActivity
MainActivity -> StandardActivity -> SingleTopActivity
//栈内容
com.example.launchmodetest/.SingleTopActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 4. 启动 StandardActivity
MainActivity -> StandardActivity -> SingleTopActivity -> StandardActivity
//栈内容
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.SingleTopActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 5. 启动 SingleTopActivity:
MainActivity -> StandardActivity -> SingleTopActivity
-> StandardActivity -> SingleTopActivity
//栈内容
com.example.launchmodetest/.SingleTopActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.SingleTopActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
// 这里由于第三个 SingleTopActivity 不在栈顶,栈顶是 StandardActivity ,
// 所以启动新的 SingleTopActivity 时会重新创建 SingleTopActivity
测试2 : SingleTopActivity 在栈顶
// 1. 启动 MainActivity
MainActivity
//栈内容
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 2. 启动 StandardActivity
MainActivity -> StandardActivity
//栈内容
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 3. 启动 SingleTopActivity
MainActivity -> StandardActivity -> SingleTopActivity
//栈内容
com.example.launchmodetest/.SingleTopActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 4. 启动 SingleTopActivity
MainActivity -> StandardActivity -> SingleTopActivity -> SingleTopActivity
//栈内容
com.example.launchmodetest/.SingleTopActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
//SingleTopActivity 收到 am_new_intent ,而不是创建新的 Activity
SingleTask 栈内复用模式
android:launchMode="singleTask"
- 如果不加 Affinity , 那么 SingleTask 标记的 Activity 创建还是在当前的 Task 中
- SingleTask 标记的 Activity 是栈内复用模式,如果当前 Task 内没有这个 Activity,那么创建新的 Activity,如果当前 Task 内有这个 Activity,不管他在 Task 的哪个位置,都会直接复用这个 Activity (收到 onNewIntent)
- 如果栈内复用,那么会 Clear Task 中这个 Activity 上面的其他的 Activity
测试1:SingleTask(Without Affinity)
// 1. 启动 MainActivity:
MainActivity
//栈内容:
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 2. 启动 StandardActivity
MainActivity -> StandardActivity
//栈内容:
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 3. 启动 SingleTaskActivity
MainActivity -> StandardActivity -> SingleTaskActivity
//栈内容:
com.example.launchmodetest/.SingleTaskActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 4. 启动 StandardActivity
MainActivity -> StandardActivity -> SingleTaskActivity -> StandardActivity
//栈内容:
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.SingleTaskActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 5. 启动 SingleTaskActivity
MainActivity -> StandardActivity -> SingleTaskActivity
-> StandardActivity -> SingleTaskActivity
//栈内容:
com.example.launchmodetest/.SingleTaskActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
//备注:SingleTaskActivity 收到 am_new_intent ,将其上面的 StandardActivity Clear 调
测试2:SingleTask(WithAffinity)
在 Manifest 中设置了 android:taskAffinity=”” 之后,启动 SingleTask 会启动一个新的 Task
// 1. 启动 MainActivity
MainActivity
//栈0内容:
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 2. 启动 StandardActivity
MainActivity -> StandardActivity
//栈0内容:
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 3. 启动 SingleTaskWithAffinity
MainActivity -> StandardActivity -> SingleTaskWithAffinity
//栈1内容:
com.example.launchmodetest/.SingleTaskWithAffinity
//栈0内容:
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 4. 启动 StandardActivity
MainActivity -> StandardActivity -> SingleTaskWithAffinity -> StandardActivity
//栈1内容:
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.SingleTaskWithAffinity
//栈0内容:
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 5. 启动 SingleTaskWithAffinity
MainActivity -> StandardActivity -> SingleTaskWithAffinity
-> StandardActivity -> SingleTaskWithAffinity
//栈1内容:
com.example.launchmodetest/.SingleTaskWithAffinity
//栈0内容:
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
总结
- 与 SingleTask 相比, SingleTaskWithAffinity 会创建新的 Stack
- 在 SingleTaskWithAffinity 启动 StandardActivity , 这个 StandardActivity 与 SingleTaskWithAffinity 在同一个栈
- 在栈 0 里面再启动 SingleTaskWithAffinity ,不会创建新的 Task
- 多任务里面会出现 SingleTaskWithAffinity
SingleInstance 单实例模式
android:launchMode="singleInstance"
单示例模式顾名思义,启动时,无论从哪里启动都会给 A 创建一个唯一的任务栈,后续的创建都不会再创建新的 A,除非 A 被销毁了
测试1:SingleInstance (Without Affinity)
taskAffinity=com.example.launchmodetest
// 1. 启动 MainActivity
MainActivity
//栈0内容
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 2. 启动 StandardActivity
MainActivity -> StandardActivity
//栈0内容
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 3. 启动 SingleInstanceActivity
MainActivity -> StandardActivity -> SingleInstanceActivity
//栈1内容(多任务里面没有 Task)
com.example.launchmodetest/.SingleInstanceActivity
//栈0内容
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 4. 启动 StandardActivity
MainActivity -> StandardActivity -> SingleInstanceActivity -> StandardActivity
//栈1内容(多任务里面没有 Task)
com.example.launchmodetest/.SingleInstanceActivity
//栈0内容:
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 5. 启动 SingleInstanceActivity
MainActivity -> StandardActivity -> SingleInstanceActivity
-> StandardActivity -> SingleInstanceActivity
//栈1内: (多任务里面没有 Task)
com.example.launchmodetest/.SingleInstanceActivity
//栈0内容
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 6. 启动 StandardActivity
MainActivity -> StandardActivity -> SingleInstanceActivity
-> StandardActivity -> SingleInstanceActivity -> StandardActivity
//栈1内: (多任务里面没有 Task)
com.example.launchmodetest/.SingleInstanceActivity
//栈0内容
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 7. 启动 SingleInstanceActivity
MainActivity -> StandardActivity -> SingleInstanceActivity
-> StandardActivity -> SingleInstanceActivity
-> StandardActivity -> SingleInstanceActivity
//栈1内容 (多任务里面没有 Task)
com.example.launchmodetest/.SingleInstanceActivity
//栈0内容
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
总结1
- SingleInstanceActivity 会创建新的 Task ,但是不会在多任务中出现
- SingleInstanceActivity 是全局唯一的,如果复用,其 onNewIntent 会被调用
- SingleInstanceActivity 启动新的 Activity,新的 Activity 不会在当前的 Task 里面,而是会回到上一个 Task 里面
测试2: SingleInstance (With Affinity)
在 Manifest 中设置了 android:taskAffinity=”” 之后,启动 SingleInstanceActivity 会出现在多任务中 ,其余的表现与没有设置 Affinity 一致
taskAffinity=null
// 1. 启动 MainActivity
MainActivity
//栈0内容:
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 2. 启动 StandardActivity
MainActivity -> StandardActivity
//栈0内容:
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 3. 启动 SingleInstanceWithAffinityActivity
MainActivity -> StandardActivity -> SingleInstanceWithAffinityActivity
//栈1内容:(多任务里面有 Task)
com.example.launchmodetest/.SingleInstanceWithAffinityActivity
//栈0内容:
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 4. 启动 StandardActivity
MainActivity -> StandardActivity
-> SingleInstanceWithAffinityActivity -> StandardActivity
//栈1内容:(多任务里面有 Task)
com.example.launchmodetest/.SingleInstanceWithAffinityActivity
//栈0内容:
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 5. 启动 SingleInstanceWithAffinityActivity
MainActivity -> StandardActivity -> SingleInstanceWithAffinityActivity
-> StandardActivity -> SingleInstanceWithAffinityActivity
//栈1内容:(多任务里面有 Task)
com.example.launchmodetest/.SingleInstanceWithAffinityActivity
//栈0内容:
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 6. 启动 StandardActivity
MainActivity -> StandardActivity -> SingleInstanceWithAffinityActivity
-> StandardActivity -> SingleInstanceWithAffinityActivity -> StandardActivity
//栈1内容:(多任务里面有 Task)
com.example.launchmodetest/.SingleInstanceWithAffinityActivity
//栈0内容
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
-------------------------------------------------------------------
// 7. 启动 SingleInstanceWithAffinityActivity
MainActivity -> StandardActivity -> SingleInstanceWithAffinityActivity
-> StandardActivity -> SingleInstanceWithAffinityActivity -> StandardActivity
-> SingleInstanceWithAffinityActivity
//栈1内容:(多任务里面有 Task)
com.example.launchmodetest/.SingleInstanceWithAffinityActivity
//栈0内容:
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.StandardActivity
com.example.launchmodetest/.MainActivity
一些概念
TaskAffinity
taskAffinity=null
与 Activity 有着亲和关系的任务。从概念上讲,具有相同亲和关系的 Activity 归属同一Task(从用户的角度来看,则是归属同一“ Application ”)。 Task 的亲和关系由其根 Activity 的亲和关系确定。
亲和关系确定两件事 - Activity 更改到的父项 Task(请参阅 allowTaskReparenting 属性)和通过 FLAG_ACTIVITY_NEW_TASK 标志启动 Activity 时将用来容纳它的 Task。
默认情况下,应用中的所有 Activity 都具有相同的亲和关系。您可以设置该属性来以不同方式组合它们,甚至可以将在不同应用中定义的 Activity 置于同一 Task 内。 要指定 Activity 与任何 Task 均无亲和关系,请将其设置为空字符串。
如果未设置该属性,则 Activity 继承为应用设置的亲和关系(请参阅 元素的 taskAffinity 属性)。 应用默认亲和关系的名称是 元素设置的软件包名称。
ActivityRecord、TaskRecord、ActivityStack 之间的关系
- 一个 ActivityRecord 对应一个 Activity 实例,保存了一个 Activity 的所有信息 ; 但是一个 Activity可能会有多个 ActivityRecord ,因为 Activity 可以被多次启动,这个主要取决于其启动模式。
- 一个 TaskRecord 由一个或者多个 ActivityRecord 组成,这就是我们常说的任务栈,具有后进先出的特点
- ActivityStack 则是用来管理 TaskRecord 的,包含了多个 TaskRecord
一般地,对于没有分屏功能以及虚拟屏的情况下,ActivityStackSupervisor 与ActivityDisplay 都是系统唯一;
- ActivityDisplay 主要有 Home Stack 、 App Stack、Recents Stack 这三个栈;
- 每个 ActivityStack 中可以有若干个 TaskRecord 对象;
- 每个 TaskRecord 包含如果若干个 ActivityRecord 对象;
- 每个 ActivityRecord记 录一个 Activity 信息。
下面是一个 dump 的例子,可以看到当前手机的 ActivityRecord、TaskRecord、ActivityStack
(adb shell dumpsys activity containers)
Activity 的几种类型
/** Activity type is currently not defined. */
public static final int ACTIVITY_TYPE_UNDEFINED = 0;
/** Standard activity type. Nothing special about the activity... */
public static final int ACTIVITY_TYPE_STANDARD = 1;
/** Home/Launcher activity type. */
public static final int ACTIVITY_TYPE_HOME = 2;
/** Recents/Overview activity type. There is only one activity with this type in the system. */
public static final int ACTIVITY_TYPE_RECENTS = 3;
/** Assistant activity type. */
public static final int ACTIVITY_TYPE_ASSISTANT = 4;
如果觉得文章有帮助, 欢迎分享到社交网站 , 希望能帮到大家.
原文作者:Gracker
原文链接:https://androidperformance.com/2019/09/01/Android-Activity-Lunch-Mode/
发表日期:September 1st 2019, 12:37:47 pm
更新日期:September 4th 2019, 10:15:26 pm
版权声明:本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可