Activity的启动模式(launchMode)、回退栈(backstack)和任务(Task)

进程、UI线程:

应用第一次启动时,会启动一个新的进程,该进程用应用的包名作为进程名(获取当前进程id的方法是:android.os.Process.myPid())。该进程会启动主线程ActivityThread,也叫UI线程,UI的绘制都应该在这个线程里完成。该进程里还有一些Binder服务线程,用于和系统进行通信。

Activity启动时ActivityManagerService会为其生成对应的ActivityRecord记录,并将其加入到回退栈(backstack)中,另外也会将ActivityRecord记录加入到某个Task中。ActivityRecord,backstack,Task都是ActivityManagerService的对象,由system_server进程负责维护,而不是由应用进程维护。

Task,backstack:

用户为了完成某个功能而执行的一系列操作会形成一个Activity序列,这个序列在Android应用程序中就称之为Task,它是从用户体验的角度出发,把一组组相关的Activity组织在一起而抽象出来的概念。在应用的Activity代码中,可以通过getTaskId()方法来获取当前Activity对象所在Task的Id。这些Activitys按照它们被打开的顺序,被安放在一个堆栈里(backstack)。在backstack中,属于同一个Task的ActivityRecord会放在一起,也会形成栈结构,也就是说后启动的Activity对象的ActivityRecord会放在Task的栈顶。

对于Task,我的理解是:Task是Task,进程是进程。进程为Task提供了其所需的Activity对象。例如:public class A extends Activity { ... }

如果Task1需要P进程的某个Activity类(例如上面的A)的对象,那么P就会new一个A的对象(假设叫obj1)给Task1使用;此时如果有另一个Task2也需要P进程的这个Activity类对象,那么P就会再new一个A的对象(假设叫obj2)给Task2使用。再推进一步,如果说此时obj2中调用了System.exit(0)方法,那么整个P进程就会被杀掉,obj1和obj2当然也不就复存在了。注意,此时Task还是存在的,假设现在Task1需要显示obj1这个Activity对象了,那么系统会重新创建P进程,重新new一个A的对象给Task1使用。

Activity的启动模式(launchMode):

Activity有四种启动模式:standard、singleTop、singleTask、singleInstance。可以在AndroidManifest.xml中activity标签的属性android:launchMode中设置该Activity的加载模式。

standard模式:默认的模式,以这种模式加载时,每当启动一个新的活动,必定会构造一个新的Activity实例放到backstack(目标Task)的栈顶,不管这个Activity是否已经存在于backstack中;

注:遇到一个问题,当使用standard模式打开另一个应用的activity后,杀掉task根部的activity,会使整个task中的Activity对象全部被清除

singleTop模式:如果一个以singleTop模式启动的Activity的实例已经存在于backstack的栈顶,那么再启动这个Activity时,不会创建新的实例,而是重用位于栈顶的那个实例,并且会调用该实例的onNewIntent()方法将Intent对象传递到这个实例中;如果以singleTop模式启动的Activity的一个实例已经存在于backstack中,但是不在栈顶,那么它的行为和standard模式相同,也会创建多个实例;

singleTask模式:这种模式下,每次启动一个Activity时,系统首先会在backstack中检查是否存在该活动的实例,如果存在,则直接使用该实例,并且会调用该实例的onNewIntent()方法将Intent对象传递到这个实例中(ps:不会调用onCreate方法了),并把这个活动之上的所有Activity统统清除(destroy);如果没有发现就会创建一个新的Activity实例;

几个关于singleTask模式的说明:

1,singleTask模式的Activity在整个backstack中只可以有一个ActivityRecord

2,只要两个Activity的taskAffinity属性一致,即使其中有一个Activity的启动模式为singleTask,它们对应的ActivityRecord会放在同一个task里,不管是从某个Activity跳转到singleTask类型的Activity,还是从singleTask类型的Activity跳转到其他Activity都是如此,除非跳转的其他Activity的启动模式是singleInstance。

3,假设Activity A的启动模式为singleTask,那么和A的ActivityReocord放在同一个task里的ActivityReocord所对应的Activity,必须与A的taskAffinity相同。也就是说,Activity A的ActivityReocord只会和同一应用的其它Activity的ActivityReocord放在同一个task里,并且这些同一应用的其它Activity不能设置特殊的taskAffinity。

singleInstance模式:总是在新的任务(task)中开启,并且这个新的任务中有且只有这一个实例,也就是说被该实例启动的其它Activity会自动运行于另一个Task中。当再次启动该Activity的实例时,会重新调用已存在的任务和实例。并且会调用这个实例的onNewIntent()方法,将Intent实例传递到该实例中。和singleTask相同,同一时刻在系统中只会存在一个这样的Activity实例,(singleInstance即单实例)

关于taskAffinity:

在概念上,具有相同的affinity的activity(即设置了相同taskAffinity属性的activity)属于同一个任务(task)。

默认情况下,一个应用中的所有activity具有相同的taskAffinity,即应用程序的包名。我们可以通过设置不同的taskAffinity属性给应用中的activity分组,也可以把不同应用中的activity的taskAffinity设置成相同的值。

为一个activity的taskAffinity设置一个空字符串,表明这个activity不属于任何task。


ps:singleTask模式演示:

假设Activity B的启动模式是singleTask,B所在的task里,B并没有处于栈顶,此时按HOME键,然后启动另一个应用的Activity X,则backstack的示意图是这样的:

这时,如果通过X启动B,则backstack的示意图是这样的:

跳转之后,B所在task中位于B之上的所有ActivityRecord都会被清除掉(C被清除了)

假设X是在C中启动出来的,backstack的示意图是这样的:

如果想要X与A、B、C在同一个task中,则需要确保它们的taskAffinity都是一样的,那样backstack的示意图是这样的:

这时,如果通过X启动B,则backstack的示意图是这样的:


ps:standard模式演示:

假设Activity B的启动模式是standard,B所在的task里,B并没有处于栈顶,此时按HOME键,然后启动另一个应用的Activity X,通过X再启动B,则backstack的示意图是这样的:

假设X是在C中启动出来的,则X与C在同一个task中,通过X再启动B,backstack的示意图是这样的:


ps:singleInstance模式演示:

假设Activity A,B,C属于同一应用,B的启动模式是singleInstance,其它为standard,Activity X属于另一应用。此时C调用起X,则backstack的示意图是这样的:

此时如果再从X调用起B,则backstack的示意图是这样的:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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

推荐阅读更多精彩内容