1、standard
standard模式是默认的启动模式,不用为<activity>配置android:launchMode属性即可,当然也可以指定值为standard。
standard模式是所启动的Activity都是在同一个task容器栈下,不会重新创建新的task容器栈。先压入栈的Activity实例按顺序入栈底,后入栈在栈顶,处于栈的顶部Activity实例处于活动状态,其他处于非活动状态。按物理返回键,退出当前所处活动状态Activity窗口,这样就会从task容器栈中弹出,显示在手机主屏幕上,从而,有非活动状态转换成活动的状态。其次,standard容器栈可能会存在着相同的Activity实例,只有没调用一次startActivity方法,就会创建目标Activity实例对象压入task容器栈。
2、singleTop
AndroidManifest.xml文件中<activity>launchmode属性配置singletop,那么启动实例化Activity,如果task容器栈顶存在已经激活的Activity实例,就会重用当前栈顶的Activity实例,不会再重新去实例化Activity对象。善于思考的朋友可能会问,如果要启动的目标Activity已经有实例化对象存在task容器栈里面,只是现在不处于栈顶,这样情况下,singletop启动模式会创建目标Activity实例吗?答案是肯定的。要启动的目标Activity实例正好处于栈顶,才能重用该实例,其他情况必须创建新实例。
3、singleTask
singletask模式,特别需要注意了。启动的目标Activity实例如果已经存在task容器栈中,不管当前实例处于栈的任何位置,是栈顶也好,栈底也好,还是处于栈中间,只要目标Activity实例处于task容器栈中,都可以重用该Activity实例对象,然后,把处于该Activity实例对象上面全部Activity实例清除掉,并且,task容器栈中永远只有唯一实例对象,不会存在两个相同的实例对象。所以,如果你想你的应用不管怎么启动目标Activity,都只有唯一一个实例对象,就使用这种启动模式。
4、singleInstance
singleInstance启动模式,简单说就是可以共享某个Activity。比如,应用1的任务容器栈中创建了MainActivity实例,应用2也要激活MainActivity,则不需要创建MainActivity实例,直接可以公用MainActivity实例。
尤其值得注意:应用1启动MainActivity,按home键;打开应用2启动应用1的MainActivity实例。在按home键,打开应用1,这时候应用1的界面是应该是处于MainActivity界面实例。
Android 中Activity 生命周期 跟Task 的关系,就是进栈出栈。
很多时候我们在Manifest的Activiy 配置信息中没有看到lunchMode 属性,其实没有配置这个属性就是系统默认属性 android:launchMode="standard"。同一个工程AppA在这种模式下有AfirstActivity 启动 AsecondActivity,启动代码是:
Intent intent = new Intent();
intent.setClass(this, AsecondActivity.class);
startActivity(intent);
查看log,两个taskId一样,说明两个 activity 是在同一个 任务栈 Task 中。
接下来我们让这两个Activity 不在同一个Task 中。有两种方法实现:(1)不修改启动代码,只修改 Mnaifest 中 给AsecondActivity 配置多添加 两行代码如下:
android:launchMode="singleTask"
android:taskAffinity="com.xjp"
(2)修改启动代码:
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClass(this, AsecondActivity.class);
startActivity(intent);
多添加了一行
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
在修改 Mnaifest 中AsecondActivity 配置多添加一行
android:taskAffinity="com.xjp"
查看log,AfirstActivity taskId = 8 而 AsecondActivity TaskId = 9.所以两个 activity 不是在同一个任务栈 Task 中。虽然两个activity 是在同一个工程下面。由此看出,代码里设置intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);和配置文件中设置android:launchMode="singleTask"的效果是一样的。 但是请注意,这里要两个条件满足才 会让两个activity 不在同一个Task 中。必须加上属性
android:taskAffinity="com.xjp"
有些人会奇怪,一般Manifest 配置文件中 很少看见 这个属性,这个属性的意思 是 “task 空间”=== “任务空间” 是的,当你没有设置的时候也是系统默认给设置 成为 当前应用的包名。我们这里设置 的和包名不一样。所以两个activity 的任务空间是不一样的,所以两个 activity 不在同一个 Task 中。 当然了,只是设置了android:taskAffinity="com.xjp"没有设置android:launchMode="singleTask"或者没有设置intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);两个 activity 也是在同一个任务空间的。亲测。
小结:当设置了android:launchMode="singleTask"时,系统会查找 对应的taskAffinity任务空间是否 有启动过 这个activity ,如果没有启动,则在这个taskAffinity 任务空间启动,如果有启动过,则 将 这个activity 推送到栈顶, 那么在这个activity 之上的activity 都被推送出栈了,不在任务Task 中,也就是 Ondestroy 了。当配置文件中设置了 android:launchMode="singleInstance"。不管 activity 怎么启动,都是在一个新的Task 任务中启动activity。启动的activity 唯一存在新的任务队列中,也就是这个task 队列中只能有 一个activity。
三、总结
总之,Android四大启动模式相当简单。默认standard模式,他是task容器栈可能存在相同的Activity实例;singletop模式下,重用栈顶Activity实例,栈顶不存在,则创建新的Activity实例,该模式下有可能存在相同Activity实例;singletask模式,task容器栈存在目标Activity实例,则重用该实例,task容器栈永远只有唯一activity实例,并且,其一是Activity实例被清除掉。singleinstance模式,不同应用可以共享Activity实例,并且是处于不同容器栈中