Activity的启动模式

247 阅读3分钟

standard

标准模式,这是系统默认的启动模式;在此模式下,每次启动Activity都会创建新的实例,在一个任务栈中可以有多个该Activity的实例,每个Activity的实例可以属于不同的任务栈;谁启动的这个Activity,这个Activity就会和谁在同一个任务栈。

singleTop

栈顶复用模式,在此模式下,如果要启动的Activity已经位于栈顶,那么不会创建新的Activity实例,同时它的onNewIntent方法会被回调;

singleTask

栈内复用模式,如果要启动的Activity已经位于栈内,那么再次启动该Activity不会创建新的实例,而是回调其onNewIntent方法;同时栈内位于该Activity之上的其他Activity出栈;

singleInstance

单实例模式,设置这种模式的Activity,启动时只能单独位于一个任务栈中,如果该Activity已存在,后续再启动就不会创建新的实例;

任务栈和TaskAffinity

默认情况下,应用的所有Activity都在同一个任务栈中,该任务栈的名字就是应用的包名;也可以通过设置TaskAffinity为Activity指定单独的任务栈。

设置TaskAffinity只有在添加启动标志FLAG_ACTIVITY_NEW_TASK时才会生效,而singleTask和singleInstance系统会自动为这两种模式添加FLAG_ACTIVITY_NEW_TASK,因此,设置TaskAffinity只在启动模式为singleTask和singleInstance时有效,standard和singleTop无效。

不同的任务栈可以拥有相同的TaskAffinity;准备两个Activity,通过MainActivity启动SecondActivity,SecondActivity的launchMode设为“singleInstance”且不设置TaskAffinity,观察Activity信息如下,可以看出两个Activity属于不同的任务栈,这两个任务栈的id不同,但拥有相同的TaskAffinity,即应用的包名。

Running activities (most recent first):
  TaskRecord{2c4341b #381 A=com.example.myapplication U=0 StackId=1 sz=1}
    Run #1: ActivityRecord{9c02be3 u0 com.example.myapplication/.SecondActivity t381}
  TaskRecord{d4c99b8 #380 A=com.example.myapplication U=0 StackId=1 sz=1}
    Run #0: ActivityRecord{23532af u0 com.example.myapplication/.MainActivity t380}

最近任务列表里显示的任务栈需要有不同的TaskAffinity,如果两个任务栈TaskAffinity相同,最近任务列表只会显示一个。

应用场景

“联系人”应用中有“新建联系人”的Activity,用户在“短信”应用中也可以打开“新建联系人”,用户在“短信”应用中打开“新建联系人”时,“新建联系人”的Activity会创建新的实例并放入“短信”应用的任务栈,此时再打开“联系人”应用,显示的是联系人列表页,如果继续打开“新建联系人”,“新建联系人”的Activity会再次创建并放入“联系人”应用的任务栈;这种场景下“新建联系人”的Activity使用的就是standard模式,特点是多个应用打开同一个Activity,Activity会创建多次,并进入对应应用的任务栈;

在“图库”应用中通过“邮箱”分享图片时,“编辑邮件”的Activity会在“邮箱”应用的任务栈创建,“邮箱”应用的任务栈会被放在“图库”应用的任务栈之上;这里启动和回退“编辑邮件”Activity的动画是应用间切换的动画。如果返回桌面或切换多任务,“邮箱”的任务栈会与“图库”的任务栈分开。在多任务页面可以看到两个应用,这里使用的模式是singleTask,特点是其他应用打开singleTask的Activity,Activity都会进入自己的任务栈;

Activity还有一个属性是allowTaskReparenting,如果设置为true,1.其他应用启动该Activity时,该Activity进入其他应用的任务栈(这时的切换动画是应用内切换),如果再打开该Activity自己所属应用,那么该Activity会从其他应用的任务栈进入自己应用的任务栈,位于栈顶。