目录
通过Intent中设置标记位来为Activity指定启动模式
Activity的启动模式
任务栈
TaskAffinity:任务相关性。
标识了一个Activity所需要的任务栈的名字
默认情况下任务栈的名字为应用的包名
单独指定TaskAffinity必须不能和包名相同,值为字符串,且中间必须含有包名分隔符“.”
主要和singleTask启动模式或者allowTaskReparenting属性配对使用,其他情况无意义。
allowTaskReparenting的使用
配置了该属性的activity(应用B中的activity)在其他应用(应用A)中启动后,当activity所属应用(应用B)启动时,并不直接调用应用B的主界面,而是启动该activity
任务栈分为前台任务栈和前台任务栈。
activity需要启动模式的原因
防止多次启动同一个activity需要重复创建多个实例。
activity的四个启动模式
standard、singleTop、singleTask、singleInstance。
1. standard:标准模式,系统的默认模式
典型的多实例实现,一个任务栈中可以有多个实例,每个实例也可以属于不同的任务栈。
该模式下谁启动了Activity,这个Activity就会运行在启动它的Activity所在的栈中。
注意:当使用ApplicationContext去启动standard模式的Activity会报错:
Calling startActivity from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
异常原因:非Activity类型的context并没有任务栈。
解决方法:为待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位。此时待启动Activity实际上是以singleTask模式启动的。
实测:
getApplicationContext().startActivity(new Intent(this, SecondActivity.class));
使用的版本是26,手机是华为P10,不确定是测试方法错了,还是这个问题再新版本的sdk上已经修复还是华为手机修复的。
2. singleTop:栈顶复用模式
如果新Activity处于任务栈的栈顶,Activity不会重新创建,onNewIntent会被回调,并且Activity的onCreate、onStart不会被系统调用
如果新Activity处于非任务栈的栈顶,Activity会重新创建。
实测:MainActivity为默认模式,SecondActivity为singleTop。
在SecondActivity界面启动SecondActivity
在SecondActivity界面启动MainActivity
3. singleTask:栈内复用模式
单实例模式
只要Activity在一个栈中存在,多次启动Activity不会重新创建实例,系统会回调onNewIntent。
流程如下:
实测:
1. MainActivity、SecondActivity为standard,ThirdActivity为singleTask,并且设置taskAffinity
ThirdActivity的堆栈Id和SecondActivity不一致
使用adb shell dumpsys activity查看堆栈信息
2. MainActivity、SecondActivity为standard,ThirdActivity为singleTask,不设置taskAffinity
三个Activity都在同一个栈中
3. MainActivity、SecondActivity、FouthActivity为standard,ThirdActivity为singleTask,不设置taskAffinity
在此FouthActivity中跳转ThirdActivity
将FouthActivity推出了栈。
singleTask默认具有clearTop效果,会将它上面的Activity出栈
4. singleInstance:单实例模式
加强版的singleTask
具有singleTask所有特性,除此之外具有此模式的Activity只能单独处于一个任务栈中
指定启动模式的两种方法
通过AndroidManifest指定启动模式
特点:优先级低、无法为Activity指定FLAG_ACTIVITY_CLEAR_TOP标识
android:launchMode="singleTask"
通过Intent中设置标记位来为Activity指定启动模式
特点:优先级高、无法为Activity指定singleInstance启动模式
Intent intent = new Intent();
intent.setClass(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);