Activity 的启动模式

Start

1. 概述

1.1 启动过程

Activity 之间的启动流程见下图,从图中可以看出,启动的过程中会受很多因素的影响,导致启动的现象千变万化。

启动流程
1.2 Task

管理并存放 Activity 实例的单元,它是 Activity 的组合,方便用户完成一系列操作。栈结构,符合先进后出特点。Android 系统全局统一管理 Task,Task 不属于任何 App,两个 App 的 Activity 可以放在一个 Task 内。

本文中用这样的框表示一个 Task

本文中用这样的框表示一个 Task。

本文用这样的方块表示 Activity 的对象实例

本文用这样的方块表示 Activity 的对象实例。

Task 在实际压 入Activity 和弹出 Activity

从图中可以看出 Task 在实际压入 Activity 和弹出 Activity 的现象特点。

2. 四大启动模式

2.1 Standard 模式

默认模式,此模式的 Activity 依照顺序压入 Task 中,可以被创建多个对象,不受限制。此模式的使用场景最广泛,大多数普通的 Activity 都使用此模式。

Standard 模式
2.2 SingleTop 模式

SingleTop 模式下的 Activity 的启动效果基本与默认模式相同,但比默认模式多一条限制,当 Task 顶部已有本类的实例时,无法再创建,只能调用已存在实例的 onNewIntent()

SingleTop 模式流程图

下图中的 A2 是 SingleTop 模式的 Activity:

SingleTop 模式

使用场景:避免重复创建。此模式避免连续重复创建 Activity 实例,比如由于点击 Button 跳转慢,用户连续点击而导致的多次创建。

2.3 SingleTask 模式

SingleTask 模式下的 Activity 会主动在系统中寻找属于自己的 Task 及实例,有则复用,无则创建 Task 和实例。复用时会将已存在的实例置顶并销毁阻碍的实例,调用 onNewIntent()

SingleTask 模式流程图

下图中的 A3 是 SingleTask 模式的 Activity:

SingleTask 模式

使用场景:主页面。此模式主要是为了避免系统中存在多个实例,并且避免实例存放到其他 App 的 Task 中,因此很适合主页面。

2.4 SingleInstance 模式

SingleInstance 模式下的 Activity 会主动寻找系统中是否已经存在实例,如果没有则创建一个 Task,并单独存放于其中;否则会复用已存在的实例,并把所在的 Task 移到最前端显示,调用 onNewIntent()

SingleInstance 模式流程图

下图中的 A4 是 SingleInstance 模式的 Activity:

SingleInstance 模式

使用场景:独立功能的页面。此模式适用于程序的独立功能的页面,同时拥有独立的快捷方式,比如一键加速功能。

3. 跨应用启动

3.1 Activity 的启动方式

关于 Activity 的启动方式,我们熟知的有显式启动和隐式启动两种,但身为一个追求知根知底的开发者,不能不去了解其底层含义。

显式启动准确的说是 Component 启动,也就是组件启动,是精准到系统中的某一具体组件的。

隐式启动准确的说是 Action 启动,也就是行为启动,是对要做的行为进行匹配,包含的范围会广一些。

通过下图,我们可以看出,这两种启动的区别在于 Intent 对象的创建方式不同。显式启动是通过创建 ComponentName 对象来创建 Intent 对象,而隐式启动是传递 Action 字符串来创建 Intent 对象。

隐式启动和显式启动区别

在启动其他 App 的 Activity 的具体实现上,我们通常使用的是隐式启动,如下图所示:

隐式启动

其实还可以通过显式启动的方式来启动其他 App 的 Activity,如下图所示:

显式启动
3.2 AppA 启动 AppB 的 Standard 模式 Activity

被启动的 Activity 压入启动者所在的 Task 中,同样可以被创建多个对象,不受限制,现象与同 App 内启动一样。

AppA 启动 AppB 的 Standard 模式 Activity
3.3 AppA 启动 AppB 的 SingleTop 模式 Activity

被启动的 Activity 压入启动者所在的 Task 中,当 Task 顶部已有本类的实例时,无法再创建,只能调用已存在实例的 onNewIntent()。现象与同 App 内启动一样。

AppA 启动 AppB 的 SingleTop 模式 Activity
3.4 AppA 启动 AppB 的 SingleTask 模式 Activity

会优先寻找系统中是否已存在实例,若没有会创建对应的 Task 和实例;如果有会检查其中是否已存在实例,如果没有则创建,否则会 onNewIntent() 复用并置顶,同时销毁阻碍的实例。

AppA 启动 AppB 的 SingleTask 模式 Activity
3.5 AppA 启动 AppB 的 SingleInstance 模式 Activity

会优先寻找系统中是否已存在实例,若没有会创建对应的 Task 和实例,此 Task 只能存放此一个实例;如果有就复用旧实例,将其所在的 Task 移入前台显示。

AppA 启动 AppB 的 SingleInstance 模式 Activity

4.常用 Launch Flag

4.1 Launch Flag 是什么?

Launch Flag 指的是启动 Activity 的 Intent 对象所携带的标记。会对启动的现象产生一定的影响。比如 FLAG_ACTIVITY_SINGLE_TOP、FLAG_ACTIVITY_CLEAR_TOP 等。

4.2 SINGLE_TOP

效果与启动 SingleTop 模式的 Activity 一样。

SINGLE_TOP
4.3 CLEAR_TOP

如果 Task 中已存在实例,清理已存在实例之上的其他实例,同时销毁已存在的实例并重建,走 onCreate()

CLEAR_TOP
4.4 CLEAR_TOP + SINGLE_TOP

如果 Task 中已存在实例,清理已存在实例之上的其他实例,复用已存在的实例,走 onNewIntent()

CLEAR_TOP + SINGLE_TOP
4.5 CLEAR_TOP + SINGLE_TOP + NEW_TASK

如果 Task 中已存在实例,清理已存在实例之上的其他实例,复用已存在的实例,走 onNewIntent()。并且可以在其他 Task 中实现。

适用场景:点击 Notification 的跳转:

CLEAR_TOP + SINGLE_TOP + NEW_TASK
4.6 CLEAR_TASK

销毁被启动的 Activity 所对应的 Task 内的所有 Activity 实例,新建被启动 Activity 实例,放在 Task 的底部。

适用场景:切换用户登录账号

CLEAR_TASK

注意:启动 Standard 和 SingleTop 时,CLEAR_TASK 单独使用无效,必须与 NEW_TASK 一同使用;启动 SingleTask 和 SingleInstance 时,CLEAR_TASK 单独使用有效。

7. EXCLUDE_FROM_RECENTS

当新建 Activity 并且存放在新的 Task 中的根部时,被启动的 Activity 从 RecentApp 列表中消失。

EXCLUDE_FROM_RECENTS

注意:部分手机需要先按 Home 键回到桌面,然后按 RecentApp 键,才能有效。

8. NO_HISTORY

带着这条 Flag 启动的 Activity,一旦 onStop,Activity 就会被销毁。按 Home 键就会销毁。不会留在 Recent 列表中。

适用场景:敏感信息的页面。比如输入密码的页面。

9. REORDER_TO_FRONT

将 Task 中已存在的实例,置顶,不影响其他实例。

若 Task 中已存在实例并且在顶部,那么 Task 顺序保持不变,复用旧实例,回调 onNewIntent()

若 Task 中已存在实例并且不在顶部,会将其移到 Task 顶部,其余 Activity 被向下压一层,回调 onNewIntent()

REORDER_TO_FRONT
10. TASK_ON_HOME

如果被启动的 Activity 的实例存放到了另一个 Task 中,那么按 Back 键回退的时候,当第一个 Task 中的 Activity 回退完之后,会回到桌面,而不会回到启动页面的 Task。

适用场景:使用 Activity 覆盖其他 App 的情形。

TASK_ON_HOME

5. TaskAffinity

5.1 TaskAffinity 概述

TaskAffinity 描述了 Activity 和 Task 之间的亲和性。Activity 和 Task 都有此属性,如果属性值一样,则表示他们亲和性一致。亲和性一致的 Activity 天然应该放在同一个亲和性一致的 Task 里。

此属性的值在 AndroidManifest.xml 文件中配置。

例如:android:taskAffinity=“:string”。如果不配置,默认是以 App 包名为值。

注意:SingleInstance 的 Activity 虽然单独在一个 Task 中,其 TaskAffinity 默认也是包名。

本文中用下图中不同的颜色表示不同 TaskAffinity 值的 Task 和 Activity。

TaskAffinity 值的 Task 和 Activity
5.2 同/异 App 启动不同 TaskAffinity 的 Activity

Activity 的启动,在本质上和它所属的 App 无关,只与它的 TaskAffinity 值相关。因此,上述两种情况效果一致。

注意:启动 Standard 和 SingleTop 的 Activity 时,需要携带 NEW_TASK,才能让不同 TaskAffinity 的 Activity 新建 Task。

下图中的 B1 是 Standard 模式的 Activity,B2 是 SingleTop 模式的 Activity:

下图中的 B3 是 SingleTask 模式的 Activity,B4 是 SingleInstance 模式的 Activity:

5.3 启动不同 App 但是配置了相同 TaskAffinity 值的 Activity

只要 TaskAffinity 的值一样,就会天然归属在同一个 Task 中,不管是不是一个 App。

某项目出现了点击自己的 ICON 结果弹出其他 App 的页面,正是因为 TaskAffinity 值一样。

下图中 AppA 的 A2 和 AppB 的 B2 拥有相同的 TaskAffinity 值 z,和两个 App 的默认的 TaskAffinity 值都不一样。

参考文献
[1]《Android系统源代码情境分析》罗升阳

申明:开始的图片来源网络,侵删

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