中launchMode
的launcher activity
会manifest
被忽略吗?android
文档说默认值是“launchMode
标准”,但如果这将应用于应用程序的主要活动,这对我来说不是逻辑,因为每次启动应用程序时,task
都会在应用程序中创建另一个instance
。
5 回答
好吧,我自己深入研究了 Android 资源,发现了以下内容。
启动器使用startActivityAsUser
. LauncherAppsService
意图是使用这些行构造的:
Intent launchIntent = new Intent(Intent.ACTION_MAIN);
launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
launchIntent.setComponent(component);
launchIntent.setSourceBounds(sourceBounds);
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
根据 Android 文档,该标志FLAG_ACTIVITY_NEW_TASK
意味着:
使用此标志时,如果您现在正在启动的 Activity 已经在运行任务,则不会启动新的 Activity;相反,当前任务将简单地以其上次所处的状态被带到屏幕的前面。
这有效且无条件地覆盖launchMode
应用程序中指定的(或省略为默认行为),并忽略此属性。
我认为这表明文档不够清晰(或完整)。如果没有对核心源代码进行如此深入的调查,每个人都会不时得到意想不到的结果。
你混淆了两件事。一个是launchMode
,另一个是“当用户从主屏幕选择一个应用程序图标,或者从最近的任务列表中选择一个任务时会发生什么”。这是两个完全不同的东西。
launchMode
每个Activity
都有一个指定launchMode
的(默认是"standard"
or 。"multiple"
这告诉 Android 如何启动 this Activity
,并且有许多因素可以促成对launchMode
.Intent
在哪个任务上请求启动Activity
(或者如果启动是从非活动上下文请求的,例如从 aService
或BroadcastReceiver
)。这取决于Activity
指定任务中的现有实例是否已经处于活动状态等。
从主屏幕或已安装应用程序列表中选择应用程序图标时的行为
当用户选择一个应用程序图标时,startActivity()
会使用Intent
包含以下数据的调用:
- 动作=主要
- 类别=发射器
- 组件设置为包名和
Activity
在清单中定义为 ACTION=MAIN 和 CATEGORY=LAUNCHER的类名 - 标记
FLAG_ACTIVITY_NEW_TASK
并FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
设置。
无论要启动的launchMode
定义如何,使用这样的Activity
调用都会导致以下行为:startActivity()
Intent
如果已经有一个任务关联与Activity
正在启动的任务匹配(简单来说,如果应用程序已经在运行),Android 将简单地将现有任务带到前台。而已。它不会创建任何Activity
. 它不调用onNewIntent()
任何Activity
. 除了将现有任务置于前台之外,它什么也不做。这就是为什么即使您指定launchMode="standard"
了您的启动器Activity
,Android 也不会在您每次单击应用程序图标时创建一个新实例。
如果还没有一个任务关联与Activity
正在启动的任务匹配的现有任务(简单来说,如果应用程序尚未运行),Android 将创建一个新任务并启动该Activity
任务。launchMode
在这里不起作用,因为在将单个启动Activity
到新任务时启动模式之间绝对没有区别。Android 总是会创建一个新任务,并且总是会创建一个新的实例Activity
作为该任务的根。
当用户从最近的任务列表中选择一个任务时,此行为也是相同的。如果任务仍在运行,Android 只是将任务带到前台,不启动任何新Activity
实例并且不调用onNewIntent()
. 如果任务不再运行,Android 会创建一个新任务并将启动器启动Activity
到该任务中。这里唯一的区别是如果用户从最近的任务列表中选择了一个任务,该标志FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
也被设置。Intent
我希望这回答了你的问题。
请参阅此答案FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
,以获取有关一般任务重设的非常详细的解释。
将除打开活动之外的所有内容都视为抽象实现。将活动声明为
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
将导致它首先打开。在形成 Intent 以在活动之间导航时,将覆盖后续活动。覆盖表示为意图标志。
意图附加列表:http: //developer.android.com/reference/android/content/Intent.html
使用标志作为命令,否则您将在 Manifest 中编写。
你是对的。默认模式是“标准”。
根据android文档
*在
standard
模式下,每次“标准”活动有新的意图时,都会创建一个新的类实例来响应该意图。每个实例处理一个意图。*.如果父activity有启动模式
standard
(并且upintent不包含FLAG_ACTIVITY_CLEAR_TOP
),当前activity和它的父activity都被弹出栈,并且创建父activity的一个新实例来接收导航intent。
设置为标准模式的 Activity 的行为是始终创建一个新的 Activity 以与每个发送的 Intent 单独工作。想象一下,如果发送 10 个 Intent 来撰写一封电子邮件,那么应该有 10 个活动启动来分别为每个 Intent 提供服务。因此,设备中可能会启动无限数量的此类活动。
Android pre-Lollipop 上的行为
将创建标准Activity 并将其放置在与发送 Intent 的任务相同的任务中的堆栈顶部。例如,当我们将图像从图库共享到标准 Activity 时,尽管它们来自不同的应用程序,但它将被堆叠在与描述相同的任务中。如果我们将应用程序切换到另一个应用程序,然后再切换回 Gallery,我们仍然会看到标准的 launchMode 位于 Gallery 任务的顶部。因此,如果我们需要对 Gallery 做任何事情,我们必须首先完成那个额外的 Activity 中的工作。
Android Lollipop 上的行为
如果活动来自同一个应用程序,它将像在棒棒糖之前一样工作,堆叠在任务之上。但是如果 Intent 是从不同的应用程序发送的。将创建新任务,并将新创建的 Activity 放置为如下所示的根 Activity。
来源从这里