launchMode="singleTask" 不创建新任务

Posted

技术标签:

【中文标题】launchMode="singleTask" 不创建新任务【英文标题】:launchMode="singleTask" does not create a new task 【发布时间】:2015-12-25 18:13:31 【问题描述】:

我有2个Activity:Activity A和Activity B。Activity A的启动模式是标准的,Activity B的启动模式是singleTask。

 <activity
    android:name=".AActivity"
    android:label="@string/app_name"
    android:launchMode="standard">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>

    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <data android:scheme="dd"></data>
        <data android:host="a"></data>
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
    </intent-filter>
</activity>
<activity
    android:name=".BActivity"
    android:label="@string/app_name"
    android:launchMode="singleTask">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <data android:scheme="dd"></data>
        <data android:host="b"></data>
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
    </intent-filter>
</activity>

我启动应用程序,启动器 Activity A 启动。然后我按主页按钮并返回手机的主屏幕。然后我启动浏览器应用程序并输入以下内容:

dd://b

打开活动B。系统导航到我的应用程序并在活动A之上启动活动B。此时如果我按下返回按钮,活动B被弹出并且我看到活动A。

这不是我所期望的,因为 android 文档指出:

对于 singleTask 活动,系统会创建一个新任务并在新任务的根目录中实例化该活动。但是,如果活动的实例已经存在于单独的任务中,系统会通过调用其 onNewIntent() 方法将意图路由到现有实例,而不是创建新实例。一次只能存在一个活动实例。

我从这些句子中了解到的是,在我的情况下,由于 Activity B 的实例不存在,因此应该启动一个新任务,并且它的堆栈中应该只有 Activity B(我的应用程序的另一个实例应该仍然存在于一个单独的任务中,它的堆栈中应该有 Activity A)。然后如果我在 Activity B 时按下 back,因为它是 backstack 中唯一的 Activity,它会被弹出并系统返回到浏览器。

为什么不是这样? android系统如何知道我的应用程序已打开并导航到它并在现有应用程序堆栈之上启动活动B,而不是启动我的应用程序的另一个实例并让我的应用程序的两个实例拥有自己的堆栈? 在新任务中实例化 Activity 是什么意思?谁能解释一下?

谢谢。

【问题讨论】:

【参考方案1】:

除了接受的答案之外,我还找到了对这个问题的解释。正如android文档所述:

affinity 表示活动更喜欢属于哪个任务。默认情况下,来自同一个应用程序的所有活动都具有相互关联性。因此,默认情况下,同一个应用程序中的所有活动都倾向于属于属于该应用程序的同一任务(具有活动 B 的应用程序)。但是,您可以修改活动的默认亲和性。

因此,如果您的应用正在运行,并且您启动了一个具有launchMode:singleTask 属性的 Activity,除非您明确声明 taskAffinity 属性,否则它会在同一个任务中启动该 Activity。但是,如果您在清单中明确声明亲和性:

<activity
        android:name=".BActivity"
        android:label="@string/app_name"
        android:taskAffinity=""
        android:launchMode="singleTask">
</activity>

然后它在一个新任务中启动活动。

可以通过下面的adb命令查看哪个activity属于哪个task:

adb shell dumpsys activity

另外,为了更好地理解 launchMode 概念,您可以在 Google Play 中查看以下应用:https://play.google.com/store/apps/details?id=com.novoda.demos.activitylaunchmode

【讨论】:

这进一步解释了它。很好的发现。 android 文档指出“singleTask:系统创建一个新任务并在新任务的根目录下实例化活动”。然后添加“无论活动是在新任务中启动还是在与启动它的活动相同的任务中启动,后退按钮总是将用户带到上一个活动。那么你怎么能确定“singleTask”不会启动默认有新任务?developer.android.com/guide/components/activities/…【参考方案2】:

您说您的应用在经过 A 时导航到 B。

所以,我认为你有两个堆栈。在第一个中,您只有 A,在第二个中,您只有 B。如果您向后按,则 B 会弹出并消失,但 A 存在并显示,因为 A 在 B 后面,即使 A 和 B 在单独的堆栈中。

如果你想让 B 弹出然后你回到家,尝试在从 A 调用 B 之后调用“finish()”

【讨论】:

以上是关于launchMode="singleTask" 不创建新任务的主要内容,如果未能解决你的问题,请参考以下文章

launchMode="singleTask" 不创建新任务

当使用 startActivityForResult 启动活动时,LaunchMode "singleTop" 会被忽略

Activity 为 launchMode="SingleTask" 时,进度对话框未显示 2 次

为啥行为不同?- android:launchMode="singleTask" , android:taskAffinity="" 和 Intent.FLAG

即使使用 launchMode="singleTask" 也可以启动两次活动

为啥即使另一个活动在顶部,launchMode="singleTask" 的启动器活动总是被推到后台堆栈的顶部? [复制]