可以通过启动模式定义 Activity 的新实例如何与当前任务关联, 两种方式:
(1)使用清单文件
当在清单文件中声明 Activity 时,指定该 Activity 在启动时如何与任务关联。
(2) 使用 Intent 标记(flag)
当调用 startActivity() 时,可以在 Intent 中添加一个标记
,用于声明新 Activity 如何(或是否)与当前任务相关联。
因此,如果 Activity A 启动 Activity B,A
Activity B 可在其清单中定义如何与当前任务相关联(如果关联的话),
Activity A 也可以请求 Activity B 应该如何与当前任务关联。
如果两个 Activity 都定义了 Activity B 应如何与任务关联,
将优先遵循 Activity A 的请求(在 intent 中定义),而不是 Activity B 的请求(在清单中定义)
注意:有些启动模式可通过清单文件定义,但不能通过 intent 标记定义,
同样,有些启动模式可通过 intent 标记定义,却不能在清单中定义。
1. 使用清单文件
使用 <activity> 元素的 launchMode 属性指定 Activity 应该如何与任务关联。
launchMode 属性说明了 Activity 应如何启动到任务中。
可以为 launchMode 属性指定 4 种不同的启动模式:
1.1 "standard"(默认模式)
默认值。系统在启动该 Activity 的任务中创建 Activity 的新实例,
并将 intent 传送给该实例。
Activity 可以多次实例化,每个实例可以属于不同的任务,一个任务可以拥有多个实例。
1.2 "singleTop" (栈顶最多只能有一个)
如果当前任务的顶部已存在 Activity 的实例,
则系统会通过调用其 onNewIntent() 方法来将 intent 转送给该实例,
而不是创建 Activity 的新实例。
Activity 可以多次实例化,每个实例可以属于不同的任务,
一个任务可以拥有多个实例(但前提是返回堆栈顶部的 Activity 不是该 Activity 的现有实例)。
例如,假设任务的返回堆栈包含根 Activity A 以及 Activity B、C 和位于顶部的 D(堆栈为 A-B-C-D;D 位于顶部)。
收到以 D 类型 Activity 为目标的 intent。如果 D 采用默认的 "standard" 启动模式,
则会启动该类的新实例,并且堆栈将变为 A-B-C-D-D。但是,
如果 D 的启动模式为 "singleTop",则 D 的现有实例会通过 onNewIntent() 接收 intent,
因为它位于堆栈顶部,堆栈仍为 A-B-C-D。
但是,如果收到以 B 类型 Activity 为目标的 intent,
则会在堆栈中添加 B 的新实例,即使其启动模式为 "singleTop" 也是如此。
注意:创建 Activity 的新实例后,用户可以按返回按钮返回到上一个 Activity。
但是,当由 Activity 的现有实例处理新 intent 时,
用户将无法通过按返回按钮返回到 onNewIntent() 收到新 intent 之前的 Activity 状态。
应用场景: 弹出通知中,用于显示详情的界面(Activity)声明为 singleTop, 则当A消息来临显示详情界面后,
B消息来临后,复用A消息的详情界面 (back key 后无法返回A界面)
实测:今日头条、网易新闻的通知似乎都不是这种,按back key 仍能返回到A
1.3 "singleTask" (只存在某一个task 中)
系统会创建新任务,并实例化新任务的根 Activity。
但是,如果另外的任务中已存在该 Activity 的实例,则系统会通过调用其 onNewIntent() 方法将 intent 转送到该现有实例,
而不是创建新实例。
Activity 一次只能有一个实例存在。
注意:虽然 Activity 在新任务中启动,但用户按返回按钮仍会返回到上一个 Activity。
1.4 singleInstance (task中仅有这个实例)
与 "singleTask" 相似,唯一不同的是系统不会将任何其他 Activity 启动到包含该实例的任务中。
该 Activity 始终是其任务唯一的成员;由该 Activity 启动的任何 Activity 都会在其他的任务中打开。
应用场景: 较少用这个
1.5 singleTask例子(浏览器)
再举个例子,Android 浏览器应用在 <activity> 元素中指定 singleTask 启动模式,
由此声明网络浏览器 Activity 应始终在它自己的任务中打开。
这意味着,如果您的应用发出打开 Android 浏览器的 intent,系统不会将其 Activity 置于您的应用所在的任务中,
而是会为浏览器启动一个新任务,如果浏览器已经有任务在后台运行,则会将该任务转到前台来处理新 intent。
无论 Activity 是在新任务中启动的,还是在和启动它的 Activity 相同的任务中启动,
用户按返回按钮都会回到上一个 Activity。但是,如果您启动了指定 singleTask 启动模式的 Activity,
而后台任务中已存在该 Activity 的实例,则系统会将该后台任务整个转到前台运行。
此时,返回堆栈包含了转到前台的任务中的所有 Activity,这些 Activity 都位于堆栈的顶部。
diagram_backstack_singletask_multiactivity.png
参考文献:
https://developer.android.com/guide/components/activities/tasks-and-back-stack
网友评论