Activity的启动模式最不容易掌握的就是singleTask和FLAG_ACTIVITY_NEW_TASK
针对singleTask,官方的说明如下:
The system creates a new task and instantiates the activity at the root of the new task. However, if an instance of the activity already exists in a separate task, the system routes the intent to the existing instance through a call to its onNewIntent()
method, rather than creating a new instance. Only one instance of the activity can exist at a time.
但实际上activity实例不存在的时候,也不一定会创建一个新的task。这里需要引入taskAffinity这个因素。对于Manifest中没有配置android:taskAffinity属性的Activity,其默认值就等同于packageName, 所以默认情况下同一个app的activity具有相同的taskAffinity。taskAffinity相同的情况下 Activity A启动launchMode为singleTask的Activity B时,即使B实例不存在,也不会创建一个新的task, 而是直接在A的task上加入B (A为singleInstance的情况除外,singleInstance的Activity永远独占一个task, 无论和其他Activity的taskAffinity是否相同)。taskAffinity不同的情况下 Activity A启动launchMode为singleTask的Activity B时,当B实例不存在时,会创建一个新的task,并且将B加入task底部。当B实例存在时,无论A和B的taskAffinity是否相同,都不会创建新的task和新的B实例,而是直接将B所在的task调到前台,并且销毁该task中B之上的所有Activity。
针对FLAG_ACTIVITY_NEW_TASK,官方的说明如下:
Start the activity in a new task. If a task is already running for the activity you are now starting, that task is brought to the foreground with its last state restored and the activity receives the new intent in onNewIntent()
.This produces the same behavior as the "singleTask"
launchMode
value, discussed in the previous section.
但实际上FLAG_ACTIVITY_NEW_TASK并不能等同于singleTask。以launchMode为standard, 加FLAG_ACTIVITY_NEW_TASK启动的Activity为例,singleTask的Activity全局只有一个实例,而standard + FLAG_ACTIVITY_NEW_TASK的实例创建和没有FLAG_ACTIVITY_NEW_TASK的standard Activity并没有区别,FLAG_ACTIVITY_NEW_TASK只是在task的分配上和singleTask类似,并不改变Activity是否创建新实例的逻辑。
例如, Activity A启动standard Activity B, 当A和B的taskAffinity相同时,B加不加FLAG_ACTIVITY_NEW_TASK没有任何区别。当A和B的taskAffinity不同时,如果不加FLAG_ACTIVITY_NEW_TASK, standard B的新实例会被加入A所在的task,如果加上FLAG_ACTIVITY_NEW_TASK,则系统会查找当前是否存在和B的taskAffinity相同的task。如果存在,则将standard B的新实例加入该task并将该task调到前台,如果不存在,则在前台创建一个新的task,并将standard B的新实例加入该task。
FLAG_ACTIVITY_CLEAR_TOP则可以影响实例的个数。Activity A启动standard Activity B,无论A和B的taskAffinity是否相同,当B实例已经存在时,系统会将该B实例所在的task调到前台,销毁该task中B实例及其以上的所有Activity,然后创建新的B实例并加入到该task顶部。
综上,以FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP启动standard Activity B时,其行为才类似于singleTask。区别在于当B的实例已经存在时,singleTask是销毁B实例之上的所有Activity,B实例收到onNewIntent()
;而FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP是销毁B实例以及其上的所有Activity,重新创建一个新的B实例加入到task顶部。此结论是基于实测的结果,测试代码见TestLaunchMode
参考阅读
我打赌你一定没搞明白的Activity启动模式
彻底弄懂Activity四大启动模式
Android面试一天一题
SingleTask 正解
官方说明 Tasks and Back stack