Activity launchMode 总结

当我们在 Android 应用程序中,添加 launchMode 属性,一起来看看会发生什么吧。

      
 

假设现在有 ABCDEF 个 Activity。

  • launchMode="singleTop"

    D 添加 launchMode="singleTop"

    例子 1:

    之前的 Activity 任务栈状态

    D-(D 位于任务栈的顶端)

    C

    B

    A

    从任何服务或其他应用程序或从某处启动 D

    最终的 Activity 任务栈状态

    D

    C

    B

    A

    例子 2:

    之前的 Activity 任务栈状态

    C

    B

    A

    从任何服务或其他应用程序或从某处启动 D

    最终的 Activity 任务栈状态

    D

    C

    B

    A

    例子 3:

    之前的 Activity 任务栈状态

    C

    D

    B

    A

在 AndroidStudio 中的 Terminal 窗口输入以下命令,查看当前任务栈的状态。

  • adb shell dumpsys activity xxx(当前应用程序的包名)

    TASK com.example.wyj.activitydemo id=28815
    
    ACTIVITY com.example.wyj.activitydemo/.CActivity 
    ...
    ACTIVITY com.example.wyj.activitydemo/.DActivity
    ...
    ACTIVITY com.example.wyj.activitydemo/.BActivity 
    ...
    ACTIVITY com.example.wyj.activitydemo/.AActivity 
    

    从 C 开启 D

    最终的 Activity 任务栈状态

    D-(之前的 D 没有位于栈顶,创建新的实例放置栈顶)

    C

    D

    B

    A

    再次输入 adb 命令来验证当前任务栈的状态。

    TASK com.example.wyj.activitydemo id=28815
    ACTIVITY com.example.wyj.activitydemo/.DActivity 
    ...  
    ACTIVITY com.example.wyj.activitydemo/.CActivity 
    ...
    ACTIVITY com.example.wyj.activitydemo/.DActivity 
    ...
    ACTIVITY com.example.wyj.activitydemo/.BActivity
    ...
    ACTIVITY com.example.wyj.activitydemo/.AActivity 
    
  • launchMode="singleTask"

    C 添加 launchMode="singleTask"

    例子 1:

    之前的 Activity 任务栈状态

    D

    C

    B

    A

    任务栈状态:

    TASK com.example.wyj.activitydemo id=28819
    ACTIVITY com.example.wyj.activitydemo/.DActivity 
    ...
    ACTIVITY com.example.wyj.activitydemo/.CActivity 
    ...
    ACTIVITY com.example.wyj.activitydemo/.BActivity 
    ...
    ACTIVITY com.example.wyj.activitydemo/.AActivity 
    

    启动 C

    最终的 Activity 任务栈状态

    C

    B

    A

    任务栈状态:

    TASK com.example.wyj.activitydemo id=28819
    ACTIVITY com.example.wyj.activitydemo/.CActivity 
    ...  
    ACTIVITY com.example.wyj.activitydemo/.BActivity 
    ...
    ACTIVITY com.example.wyj.activitydemo/.AActivity 
    

    注: D 被销毁

    例子 2:

    之前的 Activity 任务栈状态

    B

    A

    启动 C

    最终的 Activity 任务栈状态

    C

    B

    A

  • launchMode="singleInstance"

    E 添加 launchMode="singleInstance"

    例子1:

    D

    C

    B

    A

    启动 E

    最终的 Activity 任务栈状态

    E


    D

    C

    B

    A

    任务栈状态:

    TASK com.example.wyj.activitytest id=29880
    ACTIVITY com.example.wyj.activitytest/.DActivity 
    ... 
    ACTIVITY com.example.wyj.activitytest/.CActivity 
    ... 
    ACTIVITY com.example.wyj.activitytest/.BActivity 
    ... 
    ACTIVITY com.example.wyj.activitytest/.AActivity 
    
    ...
      
    TASK com.example.wyj.activitytest id=29881
    ACTIVITY com.example.wyj.activitytest/.EActivity
    

    注: ABCD 位于一个 任务栈,E 位于新的任务栈。

    例子2:

    在例子1的基础上,从 E 打开 F

    最终的 Activity 任务栈状态

    F

    D

    C

    B

    A


    E

    任务栈状态:

    TASK com.example.wyj.activitytest id=29887
    ACTIVITY com.example.wyj.activitytest/.EActivity 
    ...
    
    TASK com.example.wyj.activitytest id=29886
    ACTIVITY com.example.wyj.activitytest/.FActivity 
    ...
    ACTIVITY com.example.wyj.activitytest/.DActivity
    ...
    ACTIVITY com.example.wyj.activitytest/.CActivity 
    ...
    ACTIVITY com.example.wyj.activitytest/.BActivity 
    ...
    ACTIVITY com.example.wyj.activitytest/.AActivity 
    

    注: ABCDF 位于一个 任务栈,E 位于新的任务栈。

    例子3:

    之前的任务栈状态

    A

    B


    E

    从 A 打开 E

    最终的任务栈状态

    E


    A

    B

    任务栈状态:

    TASK com.example.wyj.activitytest id=29889
    ACTIVITY com.example.wyj.activitytest/.AActivity
    ...
    ACTIVITY com.example.wyj.activitytest/.BActivity
     
    ...        
     
    TASK com.example.wyj.activitytest id=29890
    ACTIVITY com.example.wyj.activitytest/.EActivity
    
  • launchMode="standard"

    B 添加 launchMode="standard"

    之前的任务栈状态

    D

    C

    B

    A

    开启 B

    最终的任务栈状态

    B- 新的实例

    D

    C

    B

    A

现在让我们通过在 Intent 设置标记位来为 Activity 指定启动模式

  • FLAG_ACTIVITY_NEW_TASK

    从 D 打开 E,并添加这个标记位

    val intent = Intent(this@DActivity, BActivity::class.java)
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    startActivity(intent)
    

    例子 1:

    之前的 Activity 任务栈状态

    D

    C

    B

    A

    最终的 Activity 任务栈状态

    E


    D

    C

    B

    A

    注: ABCD 位于一个 任务栈,E 位于新的任务栈。

    例子 2:

    从 D 开启 B,并添加这个标记位

    之前的 Activity 任务栈状态

    D

    C

    B

    A

    最终的 Activity 任务栈状态

    B


    D

    C

    B

    A

    注: ABCD 位于一个 任务栈,打开的 B 位于新的任务栈,

    其效果和在 xml 中为 Activity 指定 singleTask 启动模式相同。

  • FLAG_ACTIVITY_CLEAR_TASK

    例子 1:

    从 D 开启 E,并添加这个标记位

    之前的 Activity 任务栈状态

    D

    C

    B

    A

    最终的任务栈状态

    E

    注: 其它的 Activity 都被销毁。

    例子 2:

    从 D 开启 B,并添加这个标记位

    之前的 Activity 任务栈状态

    D

    C

    B

    A

    最终的 Activity 任务栈状态

    B

    注: 新的实例 B 被创建,其它的 Activity 被销毁。

  • FLAG_ACTIVITY_SINGLE_TOP

    其效果和在 xml 中为 Activity 指定 singleTop 启动模式相同。

  • FLAG_ACTIVITY_CLEAR_TOP

    从 D 开启 B,并添加这个标记位

    之前的 Activity 状态

    D

    C

    B

    A

    最终的 Activity 状态

    B- 旧的实例 B

    A

    注: 位于 B 上面的 Activity 被销毁,
    singleTask 启动模式和该标记位效果相同。

结语

  • 通过两种方式都可以为 Activity 设置启动模式,但还是有区别的

    • 优先级

      • 在代码中添加标记位的优先级高于 xml
    • 限定范围

      • 在 xml 中无法直接为 Activity 设定 FLAG_CLEAR_TOP 标识
      • 在代码中无法为 Activity 指定 singleInstance 模式

参考资料

  • 原文链接
  • Android 开发艺术探索

你可能感兴趣的:(Activity launchMode 总结)