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并入栈。

[转]Android的taskAffinity的更多相关文章

  1. Android的taskAffinity对四种launchMode的影响

    在Android系统中,一个application的所有Activity默认有一个相同的affinity(亲密关系,相似之处).也就是说同一个应用程序的的所有Activity倾向于属于同一个task. ...

  2. Android核心分析之二十一Android应用框架之AndroidApplication

    Android Application Android提供给开发程序员的概念空间中Application只是一个松散的表征概念,没有多少实质上的表征.在Android实际空间中看不到实际意义上的应用程 ...

  3. android 面试汇总<一>

    1.1 Android Activity Q:说下Activity的生命周期? 技术点:Activity生命周期 思路:分条解释Activity从创建到销毁整个生命周期中涉及到的方法及作用 参考回答: ...

  4. 进阶之路 | 奇妙的Activity之旅

    前言 本文已经收录到我的Github个人博客,欢迎大佬们光临寒舍: 我的GIthub博客 本篇文章需要已经具备的知识: Activity的基本概念 AndroidManifest.xml的基本概念 学 ...

  5. Android -- taskAffinity

    每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task.如果一个Activity没有显式的指明该Activity的taskAffinity,那么它的这个属性就等于Ap ...

  6. 关于Android TaskAffinity的那些事儿

    正常情况下,如果应用已经启动,并将应用切到后台,在通知栏中调起页面时,该应用的Task首先会被调起,然后会将我们的Activity显示在这个Task的顶端.手机百度的通知栏里面有一个快速搜索栏,无论什 ...

  7. Android关于Task的一些实践之SingleTask, SingleInstance和TaskAffinity

    上一篇文章粗略地介绍了一下关于Android中Task的基本知识.只是实践才是检验真理的唯一标准,所以.今天就来试验一下Task中的launchMode是否真的实现了文档所说的那样. 首先.定义三个A ...

  8. Android任务栈的运行规律

    一:前台栈表示应用A,后台栈则是应用B 前台栈/taskAffinity/launchMode 后台栈/taskAffinity/launchMode ActivityB/com.lpn.teston ...

  9. Android进阶--Acticivity的启动模式

    一.引言 我们在多次启动同一个Activity时,系统默认会重复创建多个实例,这样看上去便十分的愚蠢,所以android在设计时提供了启动模式来修改系统的默认行为.目前有四种启动模式:standard ...

随机推荐

  1. VS 2017正式版

    Visual Studio 2017正式版发布全纪录 又是一年发布季,微软借着Visual Studio品牌20周年之际,于美国太平洋时间2017年3月7日9点召开发布会议,宣布正式发布新一代开发利器 ...

  2. wpf设置设计时的ViewModel

    原文:wpf设置设计时的ViewModel wpf mvvm开发中,有些情况下,你的view不一定设置DataContext,但是你又想在设计阶段,能够自动提示你的view绑定的viewmodel的内 ...

  3. angular中通过$location获取路径(参数)的写法

    以下获取与修改的 URL 以  ( http://172.16.0.88:8100/#/homePage?id=10&a=100  ) 为例 [一]获取 (不修改URL) //1.获取当前完整 ...

  4. 贝叶斯推理(Bayes Reasoning)、独立与因式分解

    P(X,Y)=P(X)P(Y),X⊥Y P(X,Y,Z)∝ϕ1(X,Z)ϕ2(Y,Z),(X⊥Y∣∣Z) 1. Reasoning patterns causal reasoning 由原因到结果的一 ...

  5. (让你提前知道软件开发33):数据操纵语言(DML)

    文章2部分 数据库SQL语言 数据操纵语言(DML) 数据操纵语言(Data Manipulation Language,DML)包含insert.delete和update语句,用于增.删.改数据. ...

  6. 从贝叶斯模型(Bayes)到生成模型(Generative models)(生成式分类器,generative classifier)

    0. 基于贝叶斯公式的生成式分类器 生成式分类器(generative classifier)即是已知类别得样本: p(y=c|x,θ)∝p(x|y=c,θ)p(y=c|θ) p(x|y=c,θ) 称 ...

  7. 怎么快速构建自己的C/C++程序?——有关编译、静态链接和SCons

    怎么快速构建自己的C/C++程序?--有关编译.静态链接和SCons 1. 写在前面 最初写C++是在Visual Studio这个IDE里,那时我并没有makefile的概念,对程序的编译和链接的一 ...

  8. youwuku和koudaitong以及weimeng差异

    优库通过涨势没有口袋,通过口袋里的东西优库有, 就像一个商场的处理这些极端类别似, 所不同的是:1.掌上通免费,但也开始掏腰包通过用户收费,因为一些特殊的.这意味着,天下没有免费的午餐,掌上通是使用完 ...

  9. NetCore使用Jwtbearer给WebAPI添加访问控制

    原文:NetCore使用Jwtbearer给WebAPI添加访问控制 现在JWT代替session来做访问控制已经成为大部分webapi的做法,今天我们也来尝试一下 WebAPI使用NetCore2. ...

  10. WPF 4 单词拼写检查(SpellCheck)

    原文:WPF 4 单词拼写检查(SpellCheck)      在WPF中 Textbox 和RichTextBox 控件都内置了拼写检查属性,但该属性目前默认仅支持English.Spanish. ...