程序员

你真的明白Task吗?

2018-08-06  本文已影响212人  猪_队友

LauchMode

对于Activity的LauchMode想必大家都不陌生。

但是我们真的懂如何运用,或者这些Mode设计的原因是解决什么目的吗?概念总是很单薄,看的似懂非懂。所以我们需要通过场景去了解这些东西本质。才不会看了忘,忘了看,无限循环。

1、Standard

每次启动Activity都会创建一个新的实例,不管任务栈里面是否有。

注意:平时我们启动Activity都是在Activity里,但是当我们在Service或者Receiver中,我们调用的是Service和Receiver的Context,他们并不是Activity没有任务栈,那怎么办呢?添加FLAF_ACTIVITY_NEW_TASK标记位,那么它是否还新启动一个任务栈,还是沿用原来的呢?需要分情况分析,下边讲解FLAF_ACTIVITY_NEW_TASK会说明的。

2、SingleTop

位于任务栈栈顶的的Activity,再次启动的时候不需要重新创建。如果不在栈顶,那么就需要重新创建了。看名字就知道,只能在栈顶复用。

注意:我们重新复用的这个Activity的onCreate和onStart不会被系统调用,但是会调用onNewIntent这个回调,我们可以从这个方法里面获取data信息。比如getIntent()等等。

3、SingleTask

这个是重点也是难点,一定要注意这个。

栈内复用,只要Task任务栈里存在这个Activity,那么当重新启动这个Activity的时候就会复用,复用细节和SingleTop一致。默认具有clearTop作用。当Task任务栈里从底到顶分别是acitivty :ABCD,当B(LauchMode=SingleTask)再次启动的时候,他会进行复用,在复用的同时,会把它上面的Activity都清理掉,任务栈就变成了AB。

通过FLAF_ACTIVITY_NEW_TASK标志位启动的Activity会被赋值为SingleTask,并且会新建一个任务栈。

4、SingleInstance

单例模式,加强版的SingleTask,SingleTask有的他都有,而且比SingleTask还要霸道,具有此模式的Activity只能单独位于一个任务栈。当该Activity启动后,再次启动都是复用。

TaskAffinity

讲完四大启动模式,我们要讲taskAffinity,这是重点也是难点。

TaskAffinity可以翻译成 任务相关性,标志了一个Acitivty所需要的任务栈的名字。
TaskAffinity一般是和singleTask 或者allowTaskReparenting配对使用,在其他情况下也没什么作用,所以我们重点看这两个配对的使用。

1、TaskAffinity和singleTask

TaskAffinity是具有这个模式的activity的目前任务栈的名字。
待启动的Activity会运行在名字和TaskAffinity一样的任务栈中。
就是说当这个Activity(明确了TaskAffinity)是第一个的时候,会把这个任务栈命名成他TaskAffinity的名字。后续的未特殊处理的Activity都会进入这个栈。
当这个Activity(明确了TaskAffinity)不是第一个,他前面有一个栈而且里面有Activity,那么因为TaskAffinity不同(默认是包名)那么这个activity会新启一个任务栈命名为他的TaskAffinity,后续的Activity会进入他的任务栈。

2、TaskAffinity和allowTaskReparenting

举个例子:

如果A应用启动了B应用的界面(Activity) C,C的allowTaskReparenting=true,按Home键,回到主界面,然后我们在点击B应用的桌面图标打开B应用,我们发现,显示的并不是B的主Activity,而是C Activity,C的任务栈从A转移到了B。

分析:

因为A启动了C,所以C的任务栈在A,但是C是属于B的(记住这一点),因为C的TaskAffinity是和A任务栈的TaskAffinity是不同的,所以当B启动的时候,B会创建B任务栈,当C发现B的TaskAffinity和他的一样,然后就会从A任务栈中跑道B任务栈。

有意思的结论:

你捡了一条狗,好吃好喝的喂着,他也把这里当家了,但是有一天它的主人来了,他就屁颠屁颠跟着它的主人走了。

实验

当我们把这些结论写出来的时候,其实大多数人还是懵逼的,为什么呢?缺乏实际情景,还是不知道怎么应用?

我们就一一做实验,用数据和情景来学习这些知识。

顺序从上到下

1、Standard

A_acitivty (Standard)
B_activity (Standard)
C_activity (Standard)

image.png

返回栈 C -> B -> A

2、SingleTop

2、1
A_acitivty (Standard)
B_activity (Standard)
C_activity (Standard)
B_activity (SingleTop)


image.png

返回栈 B -> C -> B -> A

2、2
A_acitivty (Standard)
B_activity (Standard)
C_activity (SingleTop)
C_activity (SingleTop)

image.png

返回栈 C -> B -> A

我们发现C-> C 复用了C。且调用了onNewIntent方法。

3、SingleTask

3.1

A_acitivty (Standard)
B_activity (Standard)
C_activity (SingleTask)


image.png

返回栈 C -> B -> A
这个情景和SingleTop功能一样。

3.2

A_acitivty (SingleTask)
B_activity (Standard)
C_activity (Standard)
A_activity (SingleTask)


image.png

返回栈 A
把栈顶BC都清理了。

3.3

A_acitivty (Standard)
B_activity (Standard)
C_activity (Standard+FLAF_ACTIVITY_NEW_TASK)
C_activity (Standard)

blic void onClick(View v) {
                Intent intent = new Intent(B_Activity.this,C_Activity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);
image.png

返回栈 C -> C -> B -> A

我们发现并没有出现我们所想的那样,还是在一个任务栈
然后我们换个做法

3.4

A_acitivty (Standard)
B_activity (Standard)
MyService(FLAF_ACTIVITY_NEW_TASK)
C_activity (Standard)

 @Override
    public void onCreate() {
        super.onCreate();
        Intent intent1 = new Intent(getApplicationContext(), C_Activity.class);
        intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        getApplicationContext().startActivity(intent1);
    }
image.png

返回栈 C -> C -> B -> A

3.5

A_acitivty (Standard)
B_activity (Standard)
C_activity (SingleTask +FLAF_ACTIVITY_NEW_TASK)


image.png

怎么想换个任务栈这么难呢?书上都是骗人的吗?不是说好可以换的吗?
还好我们自己做了实验,不然你懂得~~呵呵哒。(书上并没有说错,只是没说清楚情况)
那怎么才能换一个任务栈呢?
这就用到了我们的重点TaskAffinity。

3.6

FLAG_ACTIVITY_NEW_TASK 和 TaskAffinity结合。
如果我们没有FLAG_ACTIVITY_NEW_TASK只设置TaskAffinity。 结果如下


image.png

当我们给Activity设置了TaskAffinity,并且设置了FLAG_ACTIVITY_NEW_TASK参数

  Intent intent = new Intent(B_Activity.this, C_Activity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);

 <activity android:name=".C_Activity"
           android:taskAffinity=".CCC"
            />
image.png

3.7

那么当SingleTask和TaskAffinity结合又会发生什么呢?


image.png

多么神奇的参数啊。所以TaskAffinity只会和四大模式中的SingleTast发生反应。当入栈的Activity是SingleTasK,而且有他的TaskAffinity,所以就会创建一个属于他的TaskAffinity任务栈,默认任务栈的名字是包名,所以新创建了一个任务栈。

3.8

那么当我们第一个Activity(SingleTasK)就设置TaskAffinity,后面的Activity还会进来吗?还是另起一个任务栈呢?


image.png

结论是 后面的Activity会进来这个任务栈。

FLAG_ACTIVITY_NEW_TASK

通过以上数据研究得出以下结论:
首先判断是否有与被启动的Activity相同的相关性任务栈,如果有,那么就不会重新启动一个任务栈。如果没有那么就需要重新启动一个任务栈了。

FLAG_ACTIVITY_NEW_TASK和SingleTask参数 是否开启新栈都与TastAffnity有关系,TastAffnity相同不会开启新栈,不同就会开启新栈。

4、SingleInstance

A_acitivty (Standard)
B_activity (Standard)
C_activity (SingleInstance)

image.png

返回栈C -> B -> A

SingleInstance很简单很暴力。那么如果我们第一个Activity是SingleInstance,后面的是Standard呢?


image.png

结论是SingleInstance很霸道,任务栈只能有他一个,如果有别的就新启一个任务栈。

5、TaskAffinity和allowTaskReparenting

5.1
A应用调用B应用的C(TaskAffinity,allowTaskReparenting=true)

B:MainActivity(Standard)
A:C_activity (Standard)
Home键
点击A应用的Icon,进去


image.png

我们发现,B应用打开启动主ActivityMainActivity,点击跳转A应用的C_activity。然后home键退出B应用,再点击启动A应用,但是A应用并没有打开他的主Activity(A_activity)而是又打开了C_activity。我们发现虽然都是同一个C_activity,但是任务栈变了。变成了B的任务栈,但是C_activity还是那个C_activity。

这就是著名结论:

你捡了一条狗,好吃好喝的喂着,他也把这里当家了,但是有一天它的主人来了,他就屁颠屁颠跟着它的主人走了。

6、其他情况

如果是A应用,启动了B应用的界面C

情况一:B应用的展示界面是C(Standard),按Home键返回桌面,然后A应用打开B应用的界面C,这个任务栈怎么说?


image.png

虽然跨应用了,但是还是一个任务栈。没什么区别

情况二:B应用的展示界面是C(SingleTop),按Home键返回桌面,然后A应用打开B应用的界面C,这个任务栈怎么说?


image.png

我们会发现,SingleTop跨应用的结论还是一直的的。

情况三:B应用的展示界面是C(SingleTask),按Home键返回桌面,然后A应用打开B应用的界面C,这个任务栈怎么说?


image.png

这个其实就触发了TaskAffinity,C的TaskAffinity默认是B应用的包名,A应用的TaskAffinity默认是A应用的包名,这里相当于TaskAffinity有了变化,根据SingleTask和TaskAffinity的性质,那么自然就会新起一个任务栈。

大家如果觉得有帮助的话,可以点个关注,告诉我大家想要深入探究哪些问题,希望看到哪方面的文章,我可以免费给你写专题文章。。或者私信沟通都可以。。。
希望大家多多支持。。你的一个关注,是我坚持的最大动力。。

上一篇下一篇

猜你喜欢

热点阅读