Android Activity launchMode研究

与standard模式类似,一个新的singleTop的activity的实例也可能被创建,来处理一个新的intent.

但是,如果目标task中已经有一个这个singleTop的activity的实例,并且它是在栈顶,则这个已经存在的实例将接受这个新的intent(  [onNewIntent()]( ) 方法被调用), 新的实例不会被创建.

其他的情况,比如,存在实例在目标task,但是不在栈顶;或者它在一个栈顶,却不在目标task,则新的实例都会被创建,并且放在栈顶, 这时候的行为和standard一样.

singleTask

singleTask和singleInstance唯一的区别就是,  singleTask的activity允许其他activity在它的task中.

启动模式为singleTask的activity永远在它的task的根部, 同时, 其他的activities (launch mode为standard和singleTop) 可以被启动到这个task中.

系统在启动一个activity的时候,发现它的launchMode是singleTask, 并不能保证就会真的开启一个新的task, 还会检查activity的 taskAffinity属性.

如果taskAffinity属性没有指定,默认是application的taskAffinity,名称即包名.

如果发现这个taskAffinity指定的task已经存在,则会在该task中新建一个activity; 如果该task不存在,才会新建一个task.

做了一个实验,用一个standard的activity来start一个singleTask的activity:

没有指定taskAffinity时, 它们的taskId相同, 说明它们还是在同一个task里;

为singleTask的activity指定一个新的taskAffinity后,singleTask的activity得到的taskId就和standard的不同了, 说明这时候开启了一个新的task.

在启动一个singleTask的activity实例时, 如果系统中已经存在这样一个实例, 将会把这个实例调度到task栈顶, 并清除它的task中栈上方的所有activities.

singleInstance

一个launch mode为singleInstance的activity,  不允许其他的activity在它的task中, 它自己是这个task中唯一的activity. 如果它启动另一个activity, 那个新的activity会被分配到一个不同的task中去, 就好像intent中含有FLAG_ACTIVITY_NEW_TASK Flag一样.

系统在启动一个activity的时候,如果发现它的launchMode是singleInstance,就会启动一个新的task,因为这种activity不会跟别人共用task. 所以和singleTask不同, singleInstance不需要特殊指定taskAffinity.

在singleInstance中启动的activity也不会跟它放在同一个task里, 根据要启动的activity的taskAffinity选择,可能在其他已有的task里,也可能开启新的task, 总之不是在singleInstance的task里.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

taskAffinity属性


taskAffinity属性规定了activity归属于什么task. 有相同这一属性的activities从概念上来讲, 应该属于同一个task, 从用户的角度来看, 属于同一个应用.

一个task的affinity是由它的根activity的affinity决定的.

affinity决定两件事情:

1.activity re-parented到哪个task; 可以查看 [allowTaskReparenting]( ) 属性的说明.

2.当activity被带有 FLAG_ACTIVITY_NEW_TASK flag的Intent启动时,哪个task来收容这个activity.

默认情况下, 一个application中的所有activities拥有相同的affinity.

你可以设置taskAffinity这个属性来将activities分组,也可以将不用应用中定义的activities放在同一个task里. 也即: 跨应用,跨进程的activities可以在同一个task里.

如果要设定一个activity没有对任何一个task的affinity, 可以将这个属性设为一个空字符串.

如果Activity的taskAffinity属性没有被设置, activity会继承application的这个属性. 对于application来说, 默认的affinity的名字就是manifest元素指定的包名.

所以默认情况下, 一个application中的所有activities有着相同的affinity, 名称即应用包名.

注意: 自己指定taskAffinity时,需要以应用包名开头,或者是省略包名,用点开头,后面加上一个自己取的名字. 否则会在安装时报错.

Up Navigation


在App中,所有非Home的屏都应该提供给用户一种方法,让用户通过点击action bar上的Up键, 来返回到应用逻辑上的prarent screen.

从Android 4.1,即API 16开始,可以通过activity的 android:parentActivityName 属性来指定每个activity逻辑上的parent.

通过上面的属性指定了parent之后,就可以通过  [NavUtils]( )API来navigate Up到parent了.

具体可以参见:  http://developer.android.com/training/implementing-navigation/ancestral.html

在这里想说的是, 在navigate up到一个当前stack上的activity时, 具体的行为是由parent activity的launch mode决定的.

如果parent activity是singleTop(或者up intent包含了 [FLAG_ACTIVITY_CLEAR_TOP]( ) Flag), parent activity就会被带到栈顶, 而且它的状态会被保存, Navigation intent被parent的  [onNewIntent()]( ) 方法所接收.

如果parent activity的launch mode是standard(并且up intent不包含  [FLAG_ACTIVITY_CLEAR_TOP]( ) Flag), 当前的activity和它的parent都会被弹出栈, 并且parent activity的新实例会被建立,来接收这个intent.

参考资料:


实验项目地址:  https://github.com/mengdd/HelloActivityAndFragment
activity和它的parent都会被弹出栈, 并且parent activity的新实例会被建立,来接收这个intent.

参考资料:


实验项目地址:  https://github.com/mengdd/HelloActivityAndFragment

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值