Activity的归属,也就是Activity应该在哪个Task中,Activity与Task的吸附关系。我们知道,一般情况下在同一个应用中,启动的Activity都在同一个Task中,它们在该Task中度过自己的生命周期,这些Activity是从一而终的好榜样。

那么为什么我们创建的Activity会进入这个Task中?它们会转到其它的Task中吗?如果转到其它的Task中,它们会到什么样的Task中去?

解决这些问题的关键,在于每个Activity的taskAffinity属性。

每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task。如果一个Activity没有显式的指明该 Activity的taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果 Application也没有指明,那么该taskAffinity的值就等于包名。而Task也有自己的affinity属性,它的值等于它的根 Activity的taskAffinity的值。

一开始,创建的Activity都会在创建它的Task中,并且大部分都在这里度过了它的整个生命。然而有一些情况,创建的Activity会被分配其它的Task中去,有的甚至,本来在一个Task中,之后出现了转移。我们首先分析一下android文档给我们介绍的两种情况。

第一种情况。如果该Activity的allowTaskReparenting设置为true,它进入后台,当一个和它有相同affinity的Task进入前台时,它会重新宿主,进入到该前台的task中。

我们验证一下这种情况。 
Application Activity taskAffinity allowTaskReparenting 
application1 Activity1 com.winuxxan.affinity true 
application2 Activity2 com.winuxxan.affinity false

我们创建两个工程,application1和application2,分别含有Activity1和Activity2,它们的taskAffinity相同,Activity1的allowTaskReparenting为true。

首先,我们启动application1,加载Activity1,然后按Home键,使该task(假设为task1)进入后台。然后启动application2,默认加载Activity2。

我们看到了什么现象?没错,本来应该是显示Activity2,但是我们却看到了Activity1。实际上Activity2也被加载了,只是Activity1重新宿主,所以看到了Activity1。

第二种情况。如果加载某个Activity的intent,Flag被设置成FLAG_ACTIVITY_NEW_TASK时,它会首先检查是否存在与自己taskAffinity相同的Task,如果存在,那么它会直接宿主到该Task中,如果不存在则重新创建Task。

我们来做一个测试。

我们首先写一个应用,它有两个Activity(Activity1和Activity2),AndroidManifest.xml如下:

<application android:icon="@drawable/icon" android:label="@string/app_name"> 
        <activity android:name=".Activity1" 
                  android:taskAffinity="com.winuxxan.task" 
                  android:label="@string/app_name"> 
        </activity> 
        <activity android:name=".Activity2"> 
            <intent-filter> 
                <action android:name="android.intent.action.MAIN" /> 
                <category android:name="android.intent.category.LAUNCHER" /> 
            </intent-filter> 
        </activity> 
    </application>

Activity2的代码如下:

public class Activity2 extends Activity {  
        private static final String TAG = "Activity2";  
        @Override 
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.main2);    
        }  
               
        @Override 
        public boolean onTouchEvent(MotionEvent event) {  
            Intent intent = new Intent(this, Activity1.class);  
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
            startActivity(intent);  
            return super.onTouchEvent(event);  
        }  
    }

然后,我们再写一个应用MyActivity,它包含一个Activity(MyActivity),AndroidManifest.xml如下:

<application android:icon="@drawable/icon" android:label="@string/app_name"> 
        <activity android:name=".MyActivity" 
                  android:taskAffinity="com.winuxxan.task" 
                  android:label="@string/app_name"> 
            <intent-filter> 
                <action android:name="android.intent.action.MAIN"/> 
                <category android:name="android.intent.category.LAUNCHER"/> 
            </intent-filter> 
        </activity>

我们首先启动MyActivity,然后按Home键,返回到桌面,然后打开Activity2,点击Activity2,进入Activity1。然后按返回键。

我们发现,我们进入Activity的顺序为Activity2->Activity1,而返回时顺序为 Activity1->MyActivity。这就说明了一个问题,Activity1在启动时,重新宿主到了MyActivity所在的Task 中去了。

以上是验证了文档中提出的两种TaskAffinity的用法。

下面就是见证奇迹的时刻,同志们,不要眨眼!

我们现在将上一文中的launchMode和本文讲的taskAffinity结合起来。

首先是singleTask加载模式与taskAffinity的结合。

我们还是用上一文中的singleTask的代码,这里就不在列出来了,请读者自己查阅上一文。唯一不同的就是,我们为MyActivity和Activity1设置成相同的taskAffinity,重新执行上文的测试。

我们发现测试结果令我们惊讶:从同一应用程序启动singleTask和不同应用程序启动的结果完全与上文讲的相反!

我们经过思考,就可以把从同一应用程序执行和从不同应用程序执行另种方式同一起来,得到一个结论:

当一个应用程序加载一个singleTask模式的Activity时,首先该Activity会检查是否存在与它的taskAffinity相同的Task。

1、如果存在,那么检查是否实例化,如果已经实例化,那么销毁在该Activity以上的Activity并调用onNewIntent。如果没有实例化,那么该Activity实例化并入栈。

2、如果不存在,那么就重新创建Task,并入栈。

用一个流程来表示:

然后我们来检测singleInstance模式融入taskAffinity时的情况,我们也是用上文中测试singleInstance的例子,在此不列出,读者翻阅前文查阅。唯一不同的是,我们将MyActivity和Activity2设置成相同的taskAffinity。

我们发现测试结果也有一定的出入,就是,当从singleInstance中启动Activity时,并没用重新创建一个Task,而是进入了和它具有相同affinity的MyActivity所在的Task。

于是,我们也能得到以下结论:

1、当一个应用程序加载一个singleInstance模式的Activity时,如果该Activity没有被实例化,那么就重新创建一个Task,并入栈,如果已经被实例化,那么就调用该Activity的onNewIntent;

2、singleInstance的Activity所在的Task不允许存在其他Activity,任何从该Activity加载的其它 Actiivty(假设为Activity2)都会被放入其它的Task中,如果存在与Activity2相同affinity的Task,则在该 Task内创建Activity2。如果不存在,则重新生成新的Task并入栈。

taskAffinity属性的更多相关文章

  1. Taskaffinity属性使用小结

    TaskAffinity属性小结 最近在项目中用到了TaskAffinity属性,发现这个还是挺有意思,可以用来控制activity所属的任务栈.但同时只设置这一个属性又是不能完成功能的,需要与其它属 ...

  2. 关于taskaffinity属性的作用

    意味着这activity更喜欢哪个TESK,具体见下方说明 当一个包含FLAG_ACTIVITY_NEW_TASK标志的intent启动一个activity时. 一个新的activity,默认地启动到 ...

  3. Android Activity task 相关属性

    所谓的 task ,是指用户完成某一项任务时与之交互的一组 Activity.比如用户要向开发者汇报 bug,先打开程序主页,然后打开关于页面,再点击报告 bug 按钮,打开编辑邮件页面.当前这三个 ...

  4. Activity Intent Flags及Task相关属性

    转自http://www.cnblogs.com/lwbqqyumidi/p/3775479.html 今天我们来讲一下Activity的task相关内容. 上次我们讲到Activity的四种启动模式 ...

  5. Android总结篇系列:Activity Intent Flags及Task相关属性

    同上文一样,本文主要引用自网上现有博文,并加上一些自己的理解,在此感谢原作者. 原文地址: http://blog.csdn.net/liuhe688/article/details/6761337 ...

  6. singleTask TaskAffinity allowTaskReparenting

    关于singleTask TaskAffinity allowTaskReparenting 一.Activity的LaunchMode 1.standard 2.singleTop:FLAG_ACT ...

  7. 任务栈 启动模式 Flag taskAffinity

    关于任务栈Task 栈的概念 栈(Stack)是一种常用的数据结构,栈只允许访问栈顶的元素,栈就像一个杯子,每次都只能取杯子顶上的东西,而对于栈就只能每次访问它的栈顶元素,从而可以达到保护栈顶元素以下 ...

  8. Android中与task相关的几个属性

    1.与任务相关的属性 taskAffinity :修改任何给定Activity的关联 系统使用包名标识应用的默认任务关联: taskAffinity属性取字符串值,必须不同于包名: taskAffin ...

  9. 【转】Android总结篇系列:Activity Intent Flags及Task相关属性

    [转]Android总结篇系列:Activity Intent Flags及Task相关属性 同上文一样,本文主要引用自网上现有博文,并加上一些自己的理解,在此感谢原作者. 原文地址: http:// ...

随机推荐

  1. InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings In

    InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is s ...

  2. ThreadLocal 类说明

    1 ThreadLocal 不是一个线程,而是保存线程本地化对象的容器.当运行于多线程环境的某个对象使用 ThreadLocal 维护变量时,ThreadLocal 为每一个使用该变量的线程分配一个独 ...

  3. Linux数据库:MYSQL启用和查看二进制日志

    在/etc/my.cnf文件中[mysqld]下加上: server-id = 1 (在整个Mysql集群中保证唯一) log-bin = binlog  log-bin-index = binlog ...

  4. 分享六:php脚本守护进程

    http://www.baidufe.com/item/9565cec0004cb49d25fd.html

  5. [na]二层+tcp/udp数据包格式

    标准:6+6+2+3    =17            3 思科:6+6+2+3+3=20           6 ip首部格式 tcp首部格式

  6. 【Android】5.4 下拉框(Spinner)

    分类:C#.Android.VS2015: 创建日期:2016-02-07 下拉列表框Spinner的用法和WinForms中ComboBox的用法非常相似,在Android应用中使用频次也相当高,因 ...

  7. appium安卓自动化的 常用driver方法封装

    appium安卓自动化的 常用driver方法封装 做安卓自动化的时候,很多方法写起来会造成代码冗余,把这部分封装起来 ,添加到androidUI工具类里,随时可调用 都放在这个类下面: @Compo ...

  8. 转载: 8个月从CS菜鸟到拿到Google Offer的经历+内推

    8个月从CS菜鸟到拿到Google Offer的经历+内推 http://blog.csdn.net/fightforyourdream/article/details/17094127 http:/ ...

  9. addEventListener()绑定事件的对象方法。

    addEventListener()绑定事件的对象方法.addEventListener()含有三个参数,一个是事件名称,另一个是事件执行的函数,最后一个是事件捕获,, obj.addEventLis ...

  10. CentOS更新163 yum源

    这个脚本也没啥多大意义,只是为了自己练习着写一下bash ======================================================================= ...