当我们在 Android 应用程序中,添加 launchMode 属性,一起来看看会发生什么吧。
<activity
android:name=".MainActivity"
android:launchMode="singleTop">
</activity>
假设现在有 A,B,C,D,E,F 个 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
注: A,B,C,D 位于一个 任务栈,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
注: A,B,C,D, F 位于一个 任务栈,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
注: A,B,C,D 位于一个 任务栈,E 位于新的任务栈。
例子 2:
从 D 开启 B,并添加这个标记位
之前的 Activity 任务栈状态
D
C
B
A
最终的 Activity 任务栈状态
B
D
C
B
A
注: A,B,C,D 位于一个 任务栈,打开的 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 开发艺术探索