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会从其他应用的任务栈进入自己应用的任务栈,位于栈顶。