Activity Task栈和taskAffinity

今天在看书时,接触到了taskAffinity这个属性,下面记录下所学到的知识点。

官方文档中关于taskAffinity是这么说的:
android:taskAffinity:
1.与 Activity 有着亲和关系的任务。从概念上讲,具有相同亲和关系的 Activity 归属同一任务(从用户的角度来看,则是归属同一“应用”)
2. 任务的亲和关系由其根 Activity 的亲和关系确定。
3.亲和关系确定两件事 - Activity 更改到的父项任务(请参阅 allowTaskReparenting 属性)和通过 FLAG_ACTIVITY_NEW_TASK 标志启动 Activity 时将用来容纳它的任务。
4.默认情况下,应用中的所有 Activity 都具有相同的亲和关系。您可以设置该属性来以不同方式组合它们,甚至可以将在不同应用中定义的 Activity 置于同一任务内。 要指定 Activity 与任何任务均无亲和关系,请将其设置为空字符串。如果未设置该属性,则 Activity 继承为应用设置的亲和关系(请参阅 <application> 元素的 taskAffinity 属性)。
5.应用默认亲和关系的名称是 <manifest> 元素设置的软件包名称。

taskAffinity这个参数标识了一个activity所需要的任务栈的名字,默认情况下,所有Activity所需的任务栈的名字为应用包名。当然,我们也可以为每个Activity都单独指定taskAffinity属性,这个属性值必须不能和报名相同,否则就相当于没指定;同时,不能就单一字符串,需要加“.”号,如android:taskAffinity="demo",这样会导致无法运行app到手机,应该这样android:taskAffinity="com.demo",应该是有判断是否为包名吧。

TastAffinity属性主要和singleTask启动模式或者allowTaskReparenting属性配对是哦那个,起其他情况下没有意义。
如,我把Domo中BActivity设置为:
<activity android:name=".BActivity" android:launchMode="singleTask"  android:taskAffinity="com.victor.hello"/>
其他地方不设置taskAffinity属性。
让我们运行DEMO到手机上,然后跳转到BActivity,然后运行:
adb shell dumpsys activity activities
截取我们需要的信息:
Stack #1:
Task id #12
TaskRecord{4272e588 #12 A=com.victor.hello U=0 sz=1}
Intent { cmp=com.victor.launchmode/.BActivity }
Hist #0: ActivityRecord{426e2720 u0 com.victor.launchmode/.BActivityt12}
Intent { cmp=com.victor.launchmode/.BActivity }
ProcessRecord{426102a8 8274:com.victor.launchmode/u0a230}


Task id #11
TaskRecord{42612128 #11 A=com.victor.launchmode U=0 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.victor.launchmode/.AActivity }


Hist #0: ActivityRecord{4242f088 u0 com.victor.launchmode/.AActivityt11}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.victor.launchmode/.AActivi
ty }
ProcessRecord{426102a8 8274:com.victor.launchmode/u0a230}


Running activities (most recent first):
TaskRecord{4272e588 #12 A=com.victor.hello U=0 sz=1}
Run #1: ActivityRecord{426e2720 u0 com.victor.launchmode/.BActivity t12}
TaskRecord{42612128 #11 A=com.victor.launchmode U=0 sz=1}
Run #0: ActivityRecord{4242f088 u0 com.victor.launchmode/.AActivity t11}


我们有看到上面的任务栈中Running activities (most recent first)中的信息,com.victor.launchmode是DEMOD的报名,最后一个是启动界面AActivity,然后进入到了BActivity,这标明了我们activity的入栈顺序。
再看stack中的task,Task id #11是我们的启动界面AActivity所在的任务栈名com.victor.launchmode,而由于我们设置了BActivity的任务名,所以位于栈顶的Task id #12是BActivity所在的任务名:com.victor.hello


当我们开始一个没有Intent.FLAG_ACTIVITY_NEW_TASK标志的Activity时,任务共用性affinities不会影响将会运行该新活动的Task:它总是运行在启动它的Task里。但是,如果使用了NEW_TASK标志,那么共用性(affinity)将被用来判断是否已经存在一个有相同共用性(affinity)的Task。如果是这样,这项Task将被切换到前面而新的Activity会启动于这个Task的顶层。

这种特性在您必须使用NEW_TASK标志的情况下最有用,尤其是从状态栏通知或桌面快捷方式启动活动时。结果是,当用户用这种方式启动您的应用程序时,它的当前Task将被切换到前台,而且想要查看的Activity被放在最上面。


例如:
包名:com.victor.demo
ActivityA:启动界面,standard模式;
ActivityB:启动界面,singleTask, taskaffinity:com.victor.demo1模式;
ActivityC:启动界面,singleTask, taskaffinity:com.victor.demo1模式;

按照如下启动顺序启动:A --> B --> C --> A --> B,然后按下两次返回键,其他不做任何处理。
猜猜结果?
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
答案是:回到了桌面!

分析:
由于B、C设置了taskaffinity属性,与application报名不一致,所以当启动A的时候会创建一个任务栈 com.victor.demo;由于B是singleTask模式,当启动B的时候由于设置了与application不一样的任务栈名字,所以会另外创建一个com.victor.demo1任务栈,然后把B放入;由于C与B一样,任务栈已经创建好了,放入C到com.victor.demo1栈顶即可;当再次启动A后,由于A是standard模式,又会创建一个A实例,放入com.victor.demo1栈,因为它是有C启动的;这个时候我们有两个任务栈,一个com.victor.demo,一个com.victor.demo1栈,com.victor.demo1栈中的ACTIVITY顺序是B-C-A,当A启动B后,由于B是一个singletask,所有C,A会出栈,当按下一个返回键,B出栈,回到A,再次按下则A销毁,回到了我们的桌面。


另外一个跟 Task 有关的 manifest文件中Activity的特性值: android:allowTaskReparenting
用来标记Activity能否从启动的Task移动到有着affinity的Task(当这个Task进入到前台时)
“true”,表示能移动,“false”,表示它必须呆在启动时呆在的那个Task里。
如果这个特性没有被设定,设定到<application>元素上的allowTaskReparenting特性的值会应用到Activity上。默认值为“false”。
一般来说,当Activity启动后,它就与启动它的Task关联,并且在那里耗尽它的整个生命周期。当当前的Task不再显示时,你可以使用这个特性来强制Activity移动到有着affinity的Task中。典型用法是:把一个应用程序的Activity移到另一个应用程序的主Task中。
例如,如果 email中包含一个web页的链接,点击它就会启动一个Activity来显示这个页面。这个Activity是由Browser应用程序定义的,但是,现在它作为email Task的一部分。如果它重新宿主到Browser Task里,当Browser下一次进入到前台时,它就能被看见,并且,当email Task再次进入前台时,就看不到它了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值