4个启动模式
standard:标准模式,默认
栈内可以重复创建多个实例;
谁启动了这种模式的 Activity,新 Activity 就会运行在启动者所在的栈中
singleTop:栈顶复用
顾名思义,当Activity位于栈顶时不会开启新的Activity,会调用onNewIntent
方法
singleTask:栈内复用模式
只要 Activity 在一个栈中有实例,多次启动此 Activity 都不会创建实例,也是直接调用 onNewIntent()
。启动 singleTask 的 Activity 时,系统会先找有没有想要的任务栈,没有就新建个任务栈;有就看栈里有没有实例栈内有实例,就会把该 Activity 调到栈顶,同时 clearTop(之前在它前面的都被清除)
singleInstance:栈内唯一
一个Activity占用一个栈
Intent Flag 使用
//如果activity在task存在,拿到最顶端不会启动新的activity
intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
//如果activity在task存在,将activity之上的所有activity结束到
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//默认的跳转类型,将activity放到一个新的Task
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//如果Activty已运行到task,再次跳转不会再运行这个activity;
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
增加属性 “|”
如果需要向flag变量中增加某个FLAG,使用"|"运算符
flag |= XXX_FLAG
原因: 如果flag变量没有XXX_FLAG,则 | 完后flag对应的位为1,如果有XXX_FLAG,则 | 完后值不会变对应位还是1.
包含属性 “&”
如果需要判断flag变量中是否包含XXX_FLAG,使用"&"运算符
flag & XXX_FLAG != 0
或者 flag & XXX_FLAG = XXX_FLAG
原因: 如果flag变量里包含XXX_FLAG,则&完后flag变量对应的位为1,因为XXX_FLAG的定义保证了只有一位非0,其他位都为0,所以如果是包含的话&运算后值不为0,值为此XXX_FLAG的值,不包含的话值为0.
取消属性 “&~”
如果需要取消flag变量的XXX_FLAG, 使用 “&~”.
flag &= ~XXX_FLAG
原因: 先对XXX_FLAG进行取反 则XXX_FLAG原来非0的那一位变为0,则使用&运算符后flag变量非0的那一位变为0,则意味着flag变量不包含XXX_FLAG
多渠道处理
一般而言,换渠道打开app时我们想要的是带有CLEAR_TOP和NEW_TASK的启动,但是外部调用一般只有NEW_TASK,这也就导致我们在换渠道重新打开后有多首页的现象。
下图是我们希望的流程图,其中【扫一扫】是我们的目标软件
/**
* 本方法处理外部渠道跳转引起的问题:
* 1. 进入渠道变更时,只保留首页
* 2. 渠道变更为桌面时,回到栈顶界面
*/
private void intentFlagHandle() {
// 本方法获取跳转过来的包名
String appName = AppUtil.guessCallAppSource();
Logger.d(TAG, " appName = " + appName);
if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
// 已有首页,换渠道时
Logger.d(TAG, " === FLAG_ACTIVITY_BROUGHT_TO_FRONT === ");
if (TextUtils.isEmpty(appName)) {
Logger.d(TAG, "=== FLAG_ACTIVITY_BROUGHT_TO_FRONT === appName = " + appName);
return;
}
// 如果是桌面,返回栈顶,不建新的首页
if (appName.equals(PkgUtils.PKG_MIUI_HOME)) {
Logger.d(TAG, "=== FLAG_ACTIVITY_BROUGHT_TO_FRONT === 桌面跳入");
finish();
return;
}
// 如果是跳转渠道变更,则只保留首页,finish 所有除栈顶的 Activity
Logger.d(TAG, "=== FLAG_ACTIVITY_BROUGHT_TO_FRONT === 跳转渠道已变更");
AppManager.INSTANCE.finishOutTop();
} else {
Logger.d(TAG, " === FLAG_ACTIVITY_BROUGHT_TO_FRONT === 未拦截");
}
}
如此一来只要调用方使用了NEW_TASK
(避免我们的Activity在别的app栈里)就可以了,进入我们的代码后全由自己处理
多渠道使用同一action问题
当多渠道使用相同action启动目标app时,若目标app已打开二级界面(即非有action的Activity)时会直接打开栈顶界面,现象与从最近任务启动类似。栈顶Activity的intent没有任何信息,对应action的Activity的intent有action和flag信息,但是不会走生命周期。所以建议此处要做下处理,一个渠道一个action,或者自己能接受现象。
最近任务栏
有时候 通过后台唤醒的 Activity 在结束任务后,不想让用户看到,这时候,需要自动的将它隐藏
通过代码隐藏
常规的关闭Activity 是 finish() ,但是如果想Activity关闭后不显示在最近任务中,则需要通过 finishAndRemoveTask()
来关闭
清单文件中配置
在需要隐藏的那个Activity 配置android:excludeFromRecents="true"
即可