Activity4种启动模式

Activity的正确打开方式

 android任务栈简单了解

android任务栈又称为Task,它是一个栈结构,具有后进先出的特性,用于存放我们的Activity组件。

下面开始介绍4种启动模式

Default模式

“default”模式是activity默认启动的模式,当你未给当前跳转的activity设置启动模式时,系统自动为你的activity设置启动模式。

SingleTop

“singletop”模式顾名思义,activity在目标的栈顶,当启动这个activity时,系统会检测当前activity是否存在在栈顶,若在栈顶系统将通过 onNewIntent 的方法将 intent 传递给已有的那个实例而不会新创建一个的实例,若不存在则会创建新的实例,而不会清除栈顶的activity。

SingleTask

“singletask”此模式最难理解,下面我们特举例子
场景:我们有两个activity,A和B,A的启动模式为default,B的启动模式为singletask,A——B
按我们理解应该出现以下的情况,而我们想的也是这样
Task 1 Task 2
A B
但实际出现在我们眼帘的不是这样,而是
Task 1 Task 2
B  
A (null)
                      图1
这时你们会说,哇靠,什么玩意,这时就引用出一个属性 android:taskAffinity   属性
我们为B在 manifes中设置此属性(android:taskAffinity="task2":

Task 1 Task 2
A B
                                                                                            图2

     这时我们恍然大悟,原来默认的 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
假如, 你需要在 service 在后台中做一些耗时操作,当它完成时, 你需要从此 service 中跳转进入一个 Activity 中, Service 是  Context  一种扩展, 它含有  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);
此为正解










  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值