关于TaskAffinity的使用

下面是谷歌官方文档对于Affinity的介绍,后面是我关于Affinity的翻译(总结)和测试。

The affinity comes into play in two circumstances:

When the intent that launches an activity contains the FLAG_ACTIVITY_NEW_TASK flag.
A new activity is, by default, launched into the task of the activity that called startActivity(). It's pushed onto the same back stack as the caller. However, if the intent passed to startActivity() contains the FLAG_ACTIVITY_NEW_TASK flag, the system looks for a different task to house the new activity. Often, it's a new task. However, it doesn't have to be. If there's already an existing task with the same affinity as the new activity, the activity is launched into that task. If not, it begins a new task.
If this flag causes an activity to begin a new task and the user presses the Home button to leave it, there must be some way for the user to navigate back to the task. Some entities (such as the notification manager) always start activities in an external task, never as part of their own, so they always put FLAG_ACTIVITY_NEW_TASK in the intents they pass to startActivity(). If you have an activity that can be invoked by an external entity that might use this flag, take care that the user has a independent way to get back to the task that's started, such as with a launcher icon (the root activity of the task has a CATEGORY_LAUNCHER intent filter; see the Starting a task section below).
When an activity has its allowTaskReparenting attribute set to "true".
In this case, the activity can move from the task it starts to the task it has an affinity for, when that task comes to the foreground.
For example, suppose that an activity that reports weather conditions in selected cities is defined as part of a travel application. It has the same affinity as other activities in the same application (the default application affinity) and it allows re-parenting with this attribute. When one of your activities starts the weather reporter activity, it initially belongs to the same task as your activity. However, when the travel application's task comes to the foreground, the weather reporter activity is reassigned to that task and displayed within it.
Tip: If an .apk file contains more than one "application" from the user's point of view, you probably want to use the taskAffinity attribute to assign different affinities to the activities associated with each "application".


Affinity的使用分两种:
1. 使用FLAG_ACTIVITY_NEW_TASK模式来启动Intent
如果Affinity里设置的Task已存在,则自动的将该Activity加入已存在的Task中;如果不存在,则启动新的Task,将Activity加入其中。
2. Activity的 allowTaskReparenting属性被设置成true
在这种情况下,当Affinity所定义的Task B显示时,Activity可以从它的启动Task A转移到B的Top进行显示。
在其他的情况中,Affinity不起作用。


下面是测试:

该测试的ManiFest文件如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.task.a"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        
        <activity android:name=".Activity0">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <activity android:name=".Activity1" />
        
        <activity android:name=".Activity2"
            android:launchMode="singleTask"
            android:taskAffinity="com.test.task.a.a1" >
            <intent-filter>
                <action android:name="com.test.task.a.Activity2" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
        
        <activity android:name=".Activity3" 
            android:allowTaskReparenting="true" />
        
        <activity android:name=".Activity4"
            android:launchMode="singleTask"/>
        
        <activity android:name=".Activity5"  />
    </application>

</manifest>
按顺序启动6个Activity:0 -> 1 -> 2 -> 3 -> 4 -> 5

调用的dumpsys activity获取的信息

可以看出: ,共分两个task:

Task #155包含Activity: 0,1,4,5

Task #153包含Activity: 2,3

 Running activities (most recent first):
   TaskRecord{41794410 #155 A com.test.task.a}
     Run #7: ActivityRecord{41317040 com.test.task.a/.Activity5}
     Run #6: ActivityRecord{412d1140 com.test.task.a/.Activity4}
   TaskRecord{4171b500 #153 A com.test.task.a.a1}
     Run #5: ActivityRecord{417b2188 com.test.task.a/.Activity3}
     Run #4: ActivityRecord{4136bca8 com.test.task.a/.Activity2}
   TaskRecord{41794410 #155 A com.test.task.a}
     Run #3: ActivityRecord{41592498 com.test.task.a/.Activity1}
     Run #2: ActivityRecord{4140ec38 com.test.task.a/.Activity0}


按Home键后,点击程序的图标再次进入程序(此时,系统会唤醒该程序的入口Activity的默认Task),再次调用dumpsys activity:

可以发现: Activity3从Task #153移出,并加入到Task #155中,且排在第一位。

  Running activities (most recent first):
    TaskRecord{41794410 #155 A com.test.task.a}
      Run #7: ActivityRecord{417b2188 com.test.task.a/.Activity3}
    TaskRecord{4158c438 #6 A com.htc.launcher}
      Run #6: ActivityRecord{412d89b8 com.htc.launcher/.Launcher}
    TaskRecord{41794410 #155 A com.test.task.a}
      Run #5: ActivityRecord{41317040 com.test.task.a/.Activity5}
      Run #4: ActivityRecord{412d1140 com.test.task.a/.Activity4}
    TaskRecord{4171b500 #153 A com.test.task.a.a1}
      Run #3: ActivityRecord{4136bca8 com.test.task.a/.Activity2}
    TaskRecord{41794410 #155 A com.test.task.a}
      Run #2: ActivityRecord{41592498 com.test.task.a/.Activity1}
      Run #1: ActivityRecord{4140ec38 com.test.task.a/.Activity0}

这个时候按后退键,Activity的退出顺序如下: 3 -> 5 -> 4 -> 1 -> 0 -> Home;


另外,有个有趣的现象:

按顺序启动6个Activity:0 -> 1 -> 2 -> 3 -> 4 -> 5;

接下来按后退键,可以发现,Activity的退出顺序如下: 5 -> 4 -> 1 -> 0 -> 3 -> 2 -> Home;

和启动的顺序不一致。 

原因如下:当启动Activity4时,Task #155被挪到Back队列的Top,而Task #153被压到下方,因此Activity的顺序改变为:Task #153(2,3) Task #155(0,1,4)
因此按下后退键的退出顺序如下: -> 4 -> 1 -> 0 -> 3 -> 2 -> Home;


猜想:
1. 每个Task是独立的Activity队列,暂称为T;Task为最小的可挪动显示单位。
2. 在Android系统中始终存在着位移的一个显示队列:这个队列的最低层是Home页面(不可移除);暂称这个队列为Back队列。
3. 每次加载程序的时候,其实是:打开程序:即取T的引用,将T加载入Back队列:若T不存在,则生成T,并将Activity放入T中,返回T的引用;若T存在,则直接返回该T的引用
4. Back可以加载多个T的引用;后退键先作用在Back队列上,再有Back队列传递给Back队列Top的T上;具体的Activity移除等,由T自己操作。
5. Home键是将Back队列里的T清空。
6. 只有Back队列会被显示。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值