Activity的四种LaunchMode和Intent 的flag的使用

时间:2021-01-16 16:44:41

Activity一共有以下四种launchMode:

1.standard

2.singleTop

3.singleTask

4.singleInstance

作用概述:规定是否新建activity,是否公用task(task:应用启动时,会创建一个对应的task。task主要负责对activity进行管理。)

使用方法:我们可以在AndroidManifest.xml配置<activity>的android:launchMode属性为以上四种之一即可,默认情况下为标准模式。



第一种模式:standard

这是系统默认的启动模式,即:不用再在AndroidManifest.xml配置<activity>的android:launchMode。

作用:标准模式下,只要用intent 跳转,系统会自动创建一个新的activity实例,并且放在栈顶。按下回退键,系统会从顶部开始一个一个清除Activity。



第二种模式:singleTop

作用:singleTop模式下,如果要跳转的activity的实例已经在栈中存在,看其是否位于栈顶,如果位于栈顶,则直接启用旧的,不在创建实例,如果不在栈顶,则创建一个新的实例。



第三种模式:singleTask

作用:如果要启动的activity的实例不存在,则创建一个新的实例。如果要启动activity的实例在栈中已经存在,则清除此activty旧实例以上的所有activity,启动旧activity的实例并且至于栈顶,开始执行OnResum()方法。



问题:启动模式为singletask,activity无法获取到intent的传值问题。

原因:

1.启动一个为启动过的activity ,会获取到新的 intent。也就是说就是启动模式设置为:singletask,第一次启动界面是传递的数据是可以接受到的。

2.当此界面再次被启动时,因为他的启动模式是:singletask,所以不会重新创建一个activity,而是启动旧的activity实例,通过getIntent()方法获取到的 intent 也是旧的Intent,没有携带新的数据。所以无法获取到数据。

解决方法:重写这个方法,并且把调用setIntent(intent),对Intent进行更新。此方法在activity(启动模式为:singletask)的界面第二次启动时,在onresume()方法之前被回调。

         @Override
protected void onNewIntent(Intent intent) {
// TODO Auto-generated method stub
super.onNewIntent(intent);
setIntent(intent);
}




第四种模式:singleInstance

作用:系统会重新启用一个栈,并且把这个activity放入新的栈中,并且保证不会再让其他的activity进入。再次跳转该activity,activity如果存在则直接启用,不存在创建新的。

注意:5.0以上的部分手机,一个应用存在多个栈的情况下,切到后台,后台会出现多个后台同一个应用的界面,这是因为界面不在同一个栈中。




Activity栈(Task)的相关知识总结:


1.Activity的affinity(亲和力)

2.Intent几种常见的flags

3.<activity>与task相关属性


第一个: Affinity(密切关系

在系统默认情况下,打开一个app,系统默认包名为affinity的值。task自身的affinity的值取决于根activity的affinity。具有相同的affinity的activity同属于一个task。


实例1:

           建立两个demo App分别命名为 A 和 B。从 A 的主界面通过意图跳转到 B 的主界面界面。此时两个app的界面位于同一个App A的栈内。如图:

Activity的四种LaunchMode和Intent 的flag的使用


           

第二个:  Intent 常用的 flag:

1.FLAG_ACTIVITY_NEW_TASK    根据Activity 的 affinity去寻找task 栈。如果一个task 的 affinity与 activity 的 affinity的相同,则                                                                      Activity会压入栈中。如果没有找到相同的,则新建立栈,并且把activity压入栈中。

实例1: 从App  A主界面跳转到 App B主界面。给Intent添加FLAG_ACTIVITY_NEW_TASK    标识。

             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);


               Activity的四种LaunchMode和Intent 的flag的使用

结果会建立两个栈。App A 的界面在App A 的栈里。App B 的界面在 App B 的栈里边。


实例2:在实例1 的基础上,在App B里添加代码,给App B的主界面 在manifest 中添加  


  <activity
            android:name="com.example.b.MainActivity"
           
android:taskAffinity="com.example.a"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="hello" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>


com.example.a为App A 的包名。这样的结果是 App A 和App B的界面会在同一个栈里。



2.FLAG_ACTIVITY_CLEAR_TOP  检查栈内是否存在要启动的Activity实例,如果存在实例,则会调用旧的Activity实例,并且清除此Activty                                                        上面的所有的activty,使其至于栈顶显示出来。

注意:1. intnet.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 跳转的页面会从 OnCreate()方法开始执行。

           2.FLAG_ACTIVITY_CLEAR_TOP  相当于 加载模式的 signleTask


3.FLAG_ACTIVITY_SINGLE_TOP  相当于加载模式的  signleTop

4.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET   如果Intent 包含此属性,那么,要跳转的activity和次activity上的所有界面,都会在task重置时被清除。(待定)


5.FLAG_ACTIVITY_NO_HISTORY  如果Intent 包含此属性,那么,要启动activity 将显示一次,不会再task栈内保存。

6.FLAG_ACTIVITY_REORDER_TO_FRONT    把已经存在的界面拿到栈顶,

例:ABCD已经存在,D通过FLAG_ACTIVITY_REORDER_TO_FRONT    去启动A,则栈内顺序BCDA。

7.FLAG_ACTIVITY_BROUGHT_TO_FRONT(测试不起作用)