Activity的正确打开方式
android任务栈简单了解
android任务栈又称为Task,它是一个栈结构,具有后进先出的特性,用于存放我们的Activity组件。
下面开始介绍4种启动模式
Default模式
SingleTop
“singletop”模式顾名思义,activity在目标的栈顶,当启动这个activity时,系统会检测当前activity是否存在在栈顶,若在栈顶系统将通过 onNewIntent 的方法将 intent 传递给已有的那个实例而不会新创建一个的实例,若不存在则会创建新的实例,而不会清除栈顶的activity。SingleTask
Task 1 | Task 2 |
---|---|
A | B |
Task 1 | Task 2 |
---|---|
B | |
A | (null) |
android:taskAffinity
属性
Task 1 | Task 2 |
---|---|
A | B |
这时我们恍然大悟,原来默认的 affinity 值就是 “包名”, 我们未给B去设置不同的taskAffinity,此时两个activity为同一个taskAffinity,所以会创建在同一个栈
用逻辑来表达就是这样:
if(taskAffinity 属性相同)
A和B在同一个Task
else
B在新的Task,并且此Task的affinity的属性是B的
Task 1 (affinity=”cn.six.adv”) | Task 2 (affinity=”task2″) |
---|---|
A | B |
图3
A(default) -> B(singleTask) -> C(singleTask) 此情况又会发生什么呢?
(1). A -> B
Task 1 (affinity=”cn.six.adv”) | Task 2 (affinity=”task2″) |
---|---|
A | B |
(2) A -> B -> C
因为 C 的 affinity 是 “task2” ,而 Task 中已经有一个和它一样属性值的 B ,所以 C 会被放在 Task 2 中。
Task 1 (affinity=”cn.six.adv”) | Task 2 (affinity=”task2″) |
---|---|
A | C B |
(3) A -> B -> C -> B
Task 1 (affinity=”cn.six.adv”) | Task 2 (affinity=”task2″) |
---|---|
A | B |
这时我们发现,C不是创建了么,都和B在同一个Task了,为什么不见了
其实是这样, C->B, B 的启动模式是 singleTask 而且它的 affinity 属性值是 “task2”, 当系统发现有一个 affinity 属性值为 task2 的 Task 2 所以就把 B 放进去了。但是, 其中已经有一个 B 的实例在 Task 2 之中。 所以系统会将已有的 B 的实例赋予一个 CLEAR_TOP(清除顶部)标志。所以 C 是这么没的。
所以总结SngleTask,当创建以SngleTask为启动模式的Activity时,系统会检测Task中有无此Activity,当存在时,系统会将已有的 B 的实例赋予一个 CLEAR_TOP(清除顶部)标志,也就是此Activity之上的全部清除,当没有时创建。
SingleInstance
SingleInstance 要比 SingleTask 好理解很多。
如果一个 Activity 的启动模式为 SingleInstance, 那么这个 Activity 必定会在一个新的 Task 之中, 并且这个 Task 之中有且只能有一个 Activity 。
再来一波栗子。
1. A(default) –> B(singleInstance) –> C(default)
(1). A -> B
Task 1 | Task 2 |
---|---|
A | B |
(2). A -> B -> C
拥有 “singleInstance” 启动模式的 activity 不予许其他任何 Activity 在它的 Task 之中。所以它是这个 Task 之中的独苗啊。当它跳转另外一个 activity 时, 那个 Activity 将会被分配到另外一个 Task 之中——就像是 intent 被赋予了 FLAG_ACTIVITY_NEW_TASK 标志一样。
由于 B 需要一个只能容纳它的 Task , 所以 C 会被加上一个 FLAG_ACTIVITY_NEW_TASK 标识。所以 C(default) 变成了 C(singleTask) 。
然后结果变成了这样:
Task 1 | Task 2 |
---|---|
c A | B |
注:如果跳转的流程是 “A(default) –> B(singleTask) –> C(default)”, 那么结果会是这样:
Task 1 | Task 2 |
---|---|
A | C B |
startActivity(intent)
方法
但当你调此方法时,你会发现报错
这就是上文中提到的。当一个 Activity A 跳转进入另一个 Activity B (它们的启动模式都为默认的 default ), 所以这个 B 会和 A 在一个 Task 之中。但是当你想让 service 跳转到 Activity B, 由于 service 并不是一个 Activity , 所以它没有相关的 task 信息。所以 Service 不会出现在 Activity 的任务栈之中。这种情况下,Activity B 就不知道自己的 Task 在哪里了。
1
2
3
4
5
|
// "this" is a service
Intent it = new Intent(this, ActivityB.class);
it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(it); |