对NEW_TASK的理解
Intent.FLAG_ACTIVITY_NEW_TASK这个flag是一个非常重要的flag,实际上,NEW_TASK这个flag可以看做一种权限:NEW_TASK不是代表新建一个Task,而是代表可以选择一个不同于当前所在Task的目标Task,即NEW的含义为不同于当前Task,而这个目标Task通过taskAffinity指定(没有显式地在Manifest中指定的话,默认为包名)。
1. 为什么SingleTask和SingleInstance不需要NEW_TASK?
答案是,系统自动将NEW_TASK添加上了。在Activity的启动流程中,ActivityStarter的startActivityInner方法会被回调,在该方法的一开始会调用一个computeLaunchingTaskFlags()方法对Intent的Flag进行加工处理:
private void computeLaunchingTaskFlags() {
...
// 表明是非Activity启动的目标Activity
if (mSourceRecord == null) {
if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
// 此时必须添加NEW_TASK
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
}
} else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
// 表明启动目标Activity的Source Activity的启动模式是SINGLE_INSTANCE,即他的Task被独占了,此时目标Activity必须添加NEW_Task
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
} else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
// 表明目标Activity的启动模式是SINGLE_INSTANCE或者SINGLE_TASK,此时需要添加NEW_TASK
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
}
}
2. 为什么SingleTask和SingleInstance系统提供支持,而其他两种模式不默认支持呢?
官方这么设计的原因,猜测是因为SingleTask和SingleInstance这两种启动模式下,一旦Activity命中了,都会有一个清除Task栈顶或者整个清除Task栈的动作,这样一来就会对Task栈中的其他Activity造成影响,因此,这种后果需要由开发者主动选择是否开启NEW_TASK承担。而根据参考文献中所述,CLEAR_TASK、CLEAR_TOP这类具有清除Task效果的标识,想要起作用,都需要配合NEW_TASK来使用,因此可以看出NEW_TASK正代表着一种权限,这种权限表明了开发者选择在taskAffinity标识的Task上启动Activity,由此可能造成的清除Task的后果,由开发者承担。
3. Activity一定会在taskAffinity指定的Task上启动吗?
这个不一定,如果taskAffinity标识的Task被一个SingleInstance模式启动的Activity先一步占领了,这时目标Activity会在一个新建的Task上启动,无论是使用CLEAR_TASK还是以SingleInstance模式启动,都不会对原来的Activity造成影响。