Android :task 与 back stack解读之进阶之路.(包括 task,back stack,lauchMode, taskAffinity ,intent flags等解析)

二、进阶之路

        通过上面的介绍,我们对Android的task,back stack有了一定的了解,一般来讲,我们不用去关注activity是怎么被放入task的,以及在back stack的存储状态。但是,有时候我们也会有一些特殊的需求。比如说,在一个新的activity启动时,我们想把它放进一个新的task中;或者启动一个activity时,我们不希望创建一个新的实例,而是使用task中已有的该activity的实例;又或者我们希望在启动一个activity时,将task中原有的activity全都销毁等等。所有的这些都可以通过使用manifest 中<activity>标签的属性以及startactivity时intent所带的flag来实现。通过它们,我们可以组合出我们想要的功能,对task进行有效的管理。

activity标签关于task的属性有:

taskAffinity
launchMode
allowTaskReparenting
clearTaskOnLaunch
alwaysRetainTaskState
finishOnTaskLaunch

参考:http://developer.android.com/guide/topics/manifest/activity-element.html

intent的flag有:

FLAG_ACTIVITY_BROUGHT_TO_FRONT

FLAG_ACTIVITY_CLEAR_TASK

FLAG_ACTIVITY_NEW_TASK

FLAG_ACTIVITY_CLEAR_TOP

FLAG_ACTIVITY_SINGLE_TOP

FLAG_ACTIVITY_MULTIPLE_TASK等

参考 http://developer.android.com/reference/android/content/Intent.html

launch mode:

launch mode 决定了activity在task中是如何被实例化的,是管理task的核心所在。我们既可以通过manifest 中activity属性来控制,也可以在start activity时,使用intent flags 来控制;当两者都有时,以manifest文件为准。

launch mode 有四个值:

"standard" 
"singleTop" 
"singleTask" 
"singleInstance"

这是它们的一个对比表格:


standard: android 默认的方式。为每一个启动的activity实例化,并放入back stack 中,并将intent指向它。

singleTop:当启动一个activity时,如果该activity已经有一个实例在back stack的顶部,那么将会用onnewintent方法启动该activity而不会创建一个新的实例;如果该activity实例不在back stack顶部或不存在,则依然会创建新的实例。下面是一个demo:

        <activity
            android:name=".activity.Activity_3"
            android:launchMode="singleTop">
        </activity>
public class Activity_3 extends BaseActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent=new Intent(this,Activity_3.class);
        startActivity(intent);
        showRunningTasks();
    }
}

与初步了解中的activity启动顺序一致,activity1启动activity2,activity2启动activity3,设置activity3为singleTop,并由activity3启动activity3

Android :task 与 back stack解读之进阶之路.(包括 task,back stack,lauchMode, taskAffinity ,intent flags等解析)_第1张图片


结果如上图,stack中只有三个activity,activity3并没有实例化一个新的对象。若是activity3改为standard,则会实例化一个新的对象,调用oncreate方法,按照上面的代码会陷入不断启动activity3的死循环中,囧,结果就不贴了~

singleTask:当task中没有该activity实例时,系统会在开启一个新的task,并且实例化该activity作为root activity;当task中存在该activity实例时,会调用activity的onnewintent方法,并不会创建一个新的实例。也就是说一个task中只会存在该activity的一个实例。下面是一个demo:

 <activity
            android:name=".activity.Activity_3"
            android:launchMode="singleTask">
        </activity>
将activity3设置为singleTask,并且activity1启动activity2,activity2启动activity3,结果:

Android :task 与 back stack解读之进阶之路.(包括 task,back stack,lauchMode, taskAffinity ,intent flags等解析)_第2张图片
细心的同学就发现问题了,不是新开一个task么,怎么activity3还在原先的task呢,这个问题[1]稍后会说。下面测试一下task中已经有实例的情况:

activity1启动activity2,activity2启动activity3,activity3启动activity1;activity1设为singleTask。结果:


activity1并没有重新创建一个新的实例,而是回到已有的实例中,而且activity1上面的activity2,activity3将会被销毁,将activity1置于栈顶。最后的task如上图右所示。

singleInstance:跟singleTask基本一致,除了一点:当activity设置为singleInstance时,其所在的task不会再放入其他activity。该activity是task中唯一的成员,由其启动的activity将会放入其他task中。demo如下:

activity1启动activity2,activity2启动activity3,activity3启动activity1;activity1设为singleInstance。结果:

Android :task 与 back stack解读之进阶之路.(包括 task,back stack,lauchMode, taskAffinity ,intent flags等解析)_第3张图片

activity1在一个task中,而activity2,activity3放入了一个新的task中。activity3启动activity1时,会回到id=600的task,不会创建新的实例。

taskAffinity:

默认同一个应用中的activity属于一个task,taskAffinity决定了activity倾向于属于哪个task。通过设置taskAffinity的值,可以让activity属于特定的task。默认的值为应用的包名。taskAffinity主要有两个方面的应用:

1、带有FLAG_ACTIVITY_NEW_TASK的intent会产生一个新的task启动activity,这个task会根据taskAffinity的值来产生,如果已经有一个taskAffinity相同的task,则会将activity放入这个task,不再产生新的task。所以说FLAG_ACTIVITY_NEW_TASK不是一定会产生新的task的,取决于taskAffinity的值。不知道大家记得没,在singleTask的测试时,我们也遇到了这种情况(问题[1]),文档中说会产生新的task,但是没有产生,就是因为taskAffinity的值是一样的。所以说,要产生新的task,记得要改taskAffinity的值哦。

2、 allowTaskReparenting 设置为"true时。这种情况下,当一个askAffinity值相同的task进入前台时,activity会从当前的task转移到该taskAffinity值相同的task中。

Intent Flags

FLAG_ACTIVITY_NEW_TASK:在新的task中启动activity;如果已经有一个task包括该activity实例,那么会将该task进入前台,调用onnewintent启动该activity。

这个与launchMode的singleTask行为一致。 (官方文档时这样说的,但是我测试发现不是这样,activity是要创建的。大家可以讨论一下这里。但是这个属性可以将后台的taskAffinity值相同的task进入前台)

FLAG_ACTIVITY_SINGLE_TOP:作用与launchMode的singleTop一样。

FLAG_ACTIVITY_CLEAR_TOP:如果activity在当前task中运行,back stack中所有在它之上的activity将会被销毁,使得该activity处于栈顶,而不会重新创建一个新的实例。

测试时发现该activity却是重建的,这样使用:intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);才不会create,而是调用onnewintent。

FLAG_ACTIVITY_CLEAR_TOP经常与FLAG_ACTIVITY_NEW_TASK合用:这样的话,可以启动一个task中的root activity,该task会进入前台,而且只剩下root activity,产生了启动的效果。调用方式:intent.addFlags(FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP)

FLAG_ACTIVITY_MULTIPLE_TASK:与FLAG_ACTIVITY_NEW_TASK合用,不管是什么情况下,都会产生一个新的task,而不会尝试去寻找一个askAffinity值相同的task。

FLAG_ACTIVITY_BROUGHT_TO_FRONTlaunch mode 为 singleTask时,系统会设置该值,自己无需设置。

其他属性:

alwaysRetainTaskState:当应用的root activity 设置为TRUE时,经过长时间后,task的back stack状态将会保持下去,不会清除。

clearTaskOnLaunch当应用的root activity 设置为TRUE时,后台恢复时,清空back stack,只剩下root activity。与alwaysRetainTaskState作用相反。

finishOnTaskLaunch:与clearTaskOnLaunch作用相似,只不过只是清除该单个activity。当task重新进入前台时,该activity不再展示。

你可能感兴趣的:(stack,intent,task,back,flags,taskAffinity,lauchmode)