activity 启动模式_Activity 的启动模式

android:launchMode 有关应如何启动 Activity 的指令。共有四种模式可与 Intent 对象中的 Activity 标记(FLAG_ACTIVITY_* 常量)协同工作,以确定在调用 Activity 处理 Intent 时应执行的操作。启动模式有以下四种:

standard 标准模式

这是默认模式,每次激活 Activity 时都会创建 Activity 实例,并放入任务栈中。使用场景:大多数 Activity。

  • 本应用打开 activity 实例放入本应用,即发送 intent 的 task 栈的顶部。Activity A 启动了 Activity B (standard), 则 B 运行在 A 所在的栈中。
  • 用 ApplicationContext 去启动 standard 模式的 Activity 会报错,由于非 Activity 的 Context 并没有任务栈,所以新开的 Activity 不知道应该放哪,解决方法是指定 FLAG_ACTIVITY_NEW_TASK,这样启动的时候就会为它创建一个新的 Task,实际是以 singleTask 启动的
  • 跨应用打开仍在同一个栈中,但是 recent app 是两个页面;如果 intent flag 带有FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,则跨应用会在同一个 recent app
singleTop 栈顶复用

如果在当前任务的栈顶正好存在该 Activity 的实例,就重用该实例( 会调用实例的 onNewIntent() ),否则就会创建新的实例并放入栈顶,即使栈中已经存在该 Activity 的实例,只要不在栈顶,都会创建新的实例。使用场景如新闻类或者阅读类 App 的内容页面。

singleTask 栈内复用

会在系统中查找属性值 affinity 等于它的属性值 taskAffinity 的任务栈,如果存在则在该这个任务栈中启动,否则就在建新任务栈(affinity 值为它的 taskAffinity)启动(FLAG_ACTIVITY_NEW_TASK 同样的情况) 如果在任务栈中已经有该 Activity 的实例,就重用该实例(会调用实例的 onNewIntent() )。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移出栈(即 singleTask 有 clearTop 的效果)。如果栈中不存在该实例,将会创建新的实例放入栈中。

适用于项目首页。

会使 flagFLAG_ACTIVITY_RESET_TASK_IF_NEEDED 失效

例子:

  • 目前任务栈 S1 中情况为 ABC,此时 Activity D 以 singleTask 请求启动,需要的任务栈 S2,由于 S2, D 均不存在,则系统先创建任务栈 S2,再创建 D 放入 S2 中。
  • 若 D 需要的是 S1,其它情况同上述,则系统直接创建 D,放入栈 S1 中
  • 若 D 需要的是 S1,且 S1 的情况 ADBC,此时 D 不会重新创建,而是移除 BC,D 即为栈顶,调用 onNewIntent
singleInstance 单实例模式

加强版的 singleTask, 具有所有的特性,与 singleTask 唯一的区别 系统不会在 singleInstance activity 的 task 栈中放入任何其他的 activity 实例,「单独位于一个 task 中」

singleInstance 不要用于中间页面,如果用于中间页面,跳转会有问题,比如:A -> B (singleInstance) -> C,由于 B 是自己一个任务栈,而 AC 默认情况下是同一个栈,这样回退的时候就是 C -> A -> B 可能会让用户懵逼。

应用场景:来电界面、Launcher 页面

启动模式的使用方式
  1. Manifest.xml 静态指定,在代码中跳转时会依照指定的模式来创建 Activity
  android:name="..activity.MultiportActivity"
  android:launchMode="singleTask"/>
  1. 启动时在 Intent 中动态指定
Intent intent = new Intent();
intent.setClass(context, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);

差别:

  • 优先级方法 2 动态指定较高,同时存在时以 2 为准;
  • 范围:方法 1 无法指定 FLAG_ACTIVITY_CLEAR_TOP,方法 2 无法指定 singleInstance 模式
Activity 的 Flags
  • FLAG_ACTIVITY_NEW_TASK 如果 taskAffinity 一样则与标准模式一样新启动一个 Activity,如果不一样则新建一个 task 放该 Activity
  • FLAG_ACTIVITY_SINGLE_TOP 与 SingleTop 效果一致
  • FLAG_ACTIVITY_CLEAR_TOP 销毁目标 Activity 和它之上的所有 Activity,重新创建目标 Activity,+ FLAG_ACTIVITY_SINGLE_TOP 效果与 SingleTask 效果一致
  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 具有此标记位的 Activity 不会出如今历史 Activity 的列表中

其它 flag 查文档

activity stack 、 task
  • stack 用栈的方式管理 Activity,这样后入的 activity 会被先移除
  • Task 是指将相关的 Activity 组合到一起,以 Activity Stack 的方式进行管理,使得多个应用的 Activity 可以组合共同完成一个任务(Task)。
TaskAffinity

「值为字符串,必须包含分隔符"."」

用来控制 Activity 所属的任务栈,可以翻译为任务相关性。设置 activity 的启动模式为 singleTask 或 singleInstance 才能生效(其实 singleInstance 本来就会在新 Task 中)。

不同的 TaskStack, Affinity 可以一样。

  1. 通过在 Manifest.xml 配置
".bActivity"
            android:launchMode="singleTask"
            android:taskAffinity="task.name"/>
  1. Intent 动态设置

如果在 xml 设未设置 launchMode,只设置了 taskAffinity 则需要在 intent 时指定相关的 launchMode 的 flag

Intent intent = new Intent(aAvtivity.this, bActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

当 TaskAffinity 生效时,如已经存在相应名称的任务栈,则不会新建栈,而是在该栈的栈顶建立相应 activity;如果没有相应名称的任务栈,就会建立对应名称的新的任务栈。

最后说一下,查看当前任务栈的 adb 命令 adb shell dumpsys activity activities

推荐阅读:

状态模式

说一说 APK 的安装流程

掌握 binder 机制?驱动核心源码详解

c857deef39905e1eda266506014326c3.png

关注我

助你升职加薪

Android 面试官

89faf0d9de17b0bb7dbce4129447484e.png e30730ec8d117ef5f4280a0748d9cbd1.png 点 赞 在 看,  年薪百万
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值