Activity启动模式&Task栈

在AMS中,ActivityRecord对应一个Activity,TaskRecord对应一个Task,每个TaskRecord中保存了若干ActivityRecord,TaskRecord由taskId标识,通过getTaskId()可以获取Activity所属的Task。ActivityStack中的TaskRecord列表保存了AMS中所有的Task信息,ActivityStack、Task、Activity三者的对应关系如下:

Activity Task ActivityStack对应关系

其中ActivityStack处于ASM所属进程,ActivityThread在APP所属进程。可以看到ActivityStack中保存了TaskRecord列表,TaskRecord中保存了Activityrecord列表。在创建或者回退Activity的时候,就是对ActivityStack中TaskRecord的ActivityRecord进行出栈和入栈操作。

Task图示法:

上图是本文Task的图示法,Task标记为“Task_task名(TaskAffinity)”,Task的TaskAffinity属性是其根Activity的TaskAffinity值;Task中的Activity标记为"应用名_Activity名(TaskAffinity)”,Activity的TaskAffinity通过AndroidManifest.xml中配置。中间的黑线表示Home,黑线下方是点home键退到后台的Task。

taskAffinity:

AndroidManifest.xml中可以给应用配置taskAffinity属性,不设置默认会使用应用的包名作为taskAffinity,taskAffinity只有在FLAG_ACTIVITY_NEW_TASK、singleTask、singleInstance的时候有效。桌面打开应用,由于Launcher使用了FLAG_ACTIVITY_NEW_TASK来启动应用,所以会根据主界面设置的taskAffinity或者默认的taskAffinity来查找或创建新的Task,具有相同taskAffinity的Task推到前台。

也就是说,应用没有启动是点击桌面应用图标会启动一个新的Task,如果应用已经启动,退到home后台后,再次点击图标,会将home后台的task原封不动重新推到前台,如果rootActivity是singleTask的话,就会将rootActivity上面的Activity对象出栈,然后再将Task推到前台。

Activity启动模式

1、standard

入栈

A_b、B_c都是standard模式,A_a启动了A_b,A_b启动了B_c,B_c又启动了A_b,可以得出如下结论:被启动的Activity如果是standard模式(即使启动者和被启动者位于不同的APP),那么被启动的Activity会保存在启动者所属的Task中(不论是否设置了TaskAffinity属性),且不论该Task中是否存在被启动实例,都会创建一个新的实例压入栈中。在按back键时也是一个一个的出栈。

2、singleTop

应用A启动应用B的B_b Activity,B_b是singleTop启动模式,那么再次启动B_b时,如果栈顶元素是B_b,就不再创建B_b实例。不论启动者和被启动者是否属于同一个应用,被启动的Activity和启动的Activity都会在同一个Task中。

singleTop属性和allowTaskReparenting混合使用会出现什么场景?

allowTaskReparenting

假设所有的Activity启动模式都是standard的,这里没有加上TaskAffinity,表明该属性不影响Task的归属。有如下运行流程:

这里A_b设置了allowTaskReparenting=true;

1)、首先启动了应用A的主界面A_a,然后A_a启动了A_b,A_a和A_b都在Task_a中,这时按下home键

2)、启动应用B的主界面B_c,B_c启动了B_d,B_d又启动了A_b,由于A_b是standard的,所以B_c、B_d和A_b在同一个Task_b中,这时再按下home键

3)、再次点击桌面的A应用,系统会把Task列表中Task_a推到前台,由于A_b设置了allowTaskReparenting属性,所以Task_b中的A_b实例也被转移到了Task_a中。这就是allowTaskReparenting属性的作用,该属性在task从后台切换到前台的时候起作用。

如果设置A_b的启动模式为singleTop,上面的执行流程依然正确,但是却发现Task_a的栈顶有两个A_b实例。

3、singleTask

当一个singleTask 模式的activity 被启动时,AMS会检查是否存在与该activity 的taskAffinity 相同的task。

1)如果存在这样的task,那么检查该activity 是否已经创建,如果已创建,那么销毁在该Activity 以上的activity 并调用onNewIntent。如果activity 尚未实例化,那么创建该activity 的实例,并压入该task 栈。最后然后将该task 推到最上面。

2)如果不存在这样的task,那么就重新创建task,然后创建该activity 的实例,并入栈,然后将该task 推到最上面。

没有Home键参与

在没有Home键参与的场景下,A_b和B_b是SingleTask的,首先启动A应用的主界面A_a,然后启动A_a启动B应用的B_b,由于B_b是singleTask的,所以创建了新的Task_b。B_b启动应用A的A_b,由于A_b是singleTask的,所以没有在Task_b中创建A_b实例,而是先查找到A_b对应的Task_a,然后在Task_a中创建A_b实例,并将Task_a推到最顶层。

home场景1

启动A应用的主界面A_a,A_a是singleTask的,然后启动了A_b、A_c,这时按下home键,接着从前应用A,发现A_a上面的Activity都被弹出栈了。

home场景2

场景2中A_b是singleTask的,由于A_b不是rootActivity,所以没有出现Activity出栈操作。

home场景3

首先启动应用A的主界面A_a,然后启动A_b,A_b是singleTask的,且taskAffinity和A_a一致,按下home键之后再启动B应用的主界面B_b,生成可新的Task_b,这时候B_b启动A_b,由于A_b是singleTask的,所以B_b从Task_a中移除了,Task_a位于顶部了。

home场景4

启动A应用的主界面A_a,位于Task_a中,然后按下home键,启动应用B的主界面B_a,B_a位于Task_b中,这时候B_a启动B_b,由于B_b是singleTask的,且taskAffinity和A_a的taskAffinity一致,所以Task_a会推到前台,然后将B_b的实例塞入Task_a中。

4、singleInstance

该启动模式的activity被启动时,如果activity没有被实例化,就创建一个新的task来保存activity实例;如果已经被实例化过,就调用其onNewIntent函数,该activity所在的Task中不允许存在其余activity。

先确定应用A的主界面A_a,然后启动singleInstance的A_b,这里就创建了新的Task_b来保存A_b,然后A_b启动A_c,由于A_b具有独占Task的特性,所以需要先查找A_c的taskAffinity(不设置默认使用包名作为Taskname)对应的task是否存在,如果不存在就创建新的Task,如果存在就将Task推到前台,这里将Task_a推到了前台,并将A_c压入。

5、FLAG_ACTIVITY_NEW_TASK

启动Activity如果使用这个属性,AMS会尝试查找被启动的Activity的taskAffinity相同的Task,如果有,就直接将Task移动到前台,然后将启动的Activity压入栈;如果没有,则创建一个新的栈来保存实例。

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

推荐阅读更多精彩内容