本文不详细介绍基础概念,适合一知半解,想要彻底弄清楚的同学食用。
Activity 的 LaunchMode 有四种取值:
- standard
- singleTop
- singleTask
- singleInstance
这个取值有两方面的影响:
- 是否创建新的 Activity 实例
- 创建的 Activity 实例在哪个 task 里
是否创建新的 Activity 实例
如果创建新的 Activity 实例,那么一定是走 onCreate() > onStart() > onResume() 这个生命周期路线。
如果不创建,也就是复用之前存在的,则一定会调用 onNewIntent(),其他生命周期方法视具体情况而定。
- standard 默认模式。一定会创建新的实例。
- singleTop 栈顶复用模式。如果要启动的实例所在的task顶部已经有了一个实例,才可以复用之前。其他情况,比如:
- 原来并没有这个 Activity 的实例。
- 原来有这个 Activity 的实例,但并不在栈顶。
- 原来有这个 Activity 的实例,但是和要启动的实例不在一个 task 中。
- singleTask 栈内复用模式。如果原来有一个实例在某个 task 内,则一定会复用,不会创建新的实例。如果原来没有,则会创建实例。
- 复用的时候还有一个作用是清除掉原实例上面的所有 Activity
- singleIntance 单例模式。这种 Activity 只能存在在一个 task 中,并且这个 task 只能有这一个 Activity。与 singleTask 类似,有则复用,没有则创建。
创建的 Activity 实例在哪个 task 里
taskAffinity 属性
- 是一个字符串,是 task 在设备范围内的全局名称
- 如果不设置,taskAffinity 默认值是应用的包名
- 所有模式都可以指定这个属性,都有可能有用,见下文:
基本规则
- standard 谁启动它,就和谁在一个 task 内。
- 除非是 singleInstance 启动它,它肯定不会和 singleInstance 在一个 task 内,而是使用自己的 taskAffinity 决定。
- singleTop 与 standard 相同。
- singleTask 始终创建在 taskAffinity 指定的 task 内,如果没有则创建这个 task。
- singleInstance 始终独占一个 task,没有就创建这个 task。
验证方法
打印 taskAffinity、taskId、launchMode
private static String[] S = {
"standard", "singleTop", "singleTask", "singleInstance"};
public static String getTaskDebugString(Activity activity) {
try {
ActivityInfo info = activity.getPackageManager()
.getActivityInfo(
activity.getComponentName(),
PackageManager.GET_META_DATA);
return info.taskAffinity + "#" + activity.getTaskId()
+ "(" + S[info.launchMode] + ")";
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return "";
}
}
一些例子
以下表格表示各种组合情况下,启动 Main > A > B 的过程中,获取的 task 的信息。
以下表格内 standard(A) 表示 standard 模式,括号表示设置的 taskAffinity。
Main | A | B | Task(Main,A,B) | 解析 |
---|---|---|---|---|
standard | singleInstance | standard | X,Y,X | singleInstance就是和别人不一样 |
standard(P) | singleInstance | standard(P) | X,Y,X | 显式设置相同的 taskAffinity,其实跟不设置是一样的 |
standard(P) | singleInstance | standard(Q) | X,Y,Z | 具有不同taskAffinity的standard中间插一个singleInstance,也放在了不同的task中 |
standard(P) | singleInstance(P) | standard(P) | X,Y,X | 即使手动设置了singleInstance的taskAffinity,也是没有影响,不会和别的在一个task内 |
singleIntance | standard(P) | standard(Q) | X,Y,Y | standard启动standard会忽略taskAffinity |
standard | singleTask | standard | X,X,X | Main和A的taskAffinity相同,singleTask也不会创建新的task |
standard(P) | singleTask(P) | standard(Q) | X,Y,Y | 同上 |
standard | singleTask(P) | standard(Q) | X,Y,Y | Main和A的taskAffinity不相同了,就启动了新的task |
standard | singleTask(P) | standard | X,Y,Y | 即使B与Main的taskAffinity相同,但是standard自己决定不了task要跟启动者相同 |
singleTask(P) | singleTask(Q) | standard(P) | X,Y,Y | - |
singleTask(P) | singleTask(Q) | standard(P,NT) | X,Y,X | NT表示NEW_TASK flag |
结论
想要彻底理解 launchMode,只要记住以下几点:
- standard 和 singleTop 不自己决定 task。
- singleTask 和 singleInstance 自己决定 task。
- taskAffinity 表示任务名字,不设置默认是包名。
- NEW_TASK flag 使 Activity 有自主决定 task 的权利,taskAffinity 才有效。
网友评论