Android - Activity LaunchMode 简例

本文不详细介绍基础概念,适合一知半解,想要彻底弄清楚的同学食用。

Activity 的 LaunchMode 有四种取值:

  • standard
  • singleTop
  • singleTask
  • singleInstance

这个取值有两方面的影响:

  1. 是否创建新的 Activity 实例
  2. 创建的 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 才有效。

你可能感兴趣的:(Android - Activity LaunchMode 简例)