FLAG_ACTIVITY_RESET_TASK_IF_NEEDED和FLAG_ACTIVITY_CLEAR_TOP之间有什么区别?FLAG_ACTIVITY_SINGLE_TOP?

Com*_*are 31 android android-intent

我正在(最后)编写关于我书的任务的章节,我遇到了一些挥之不去的谜题.

作为主屏幕发射器的东西似乎使用FLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_RESET_TASK_IF_NEEDED启动请求的启动器活动时的组合:

Intent i=new Intent(Intent.ACTION_MAIN);

i.addCategory(Intent.CATEGORY_LAUNCHER);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
            Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
i.setComponent(name);

startActivity(i);  
Run Code Online (Sandbox Code Playgroud)

文档FLAG_ACTIVITY_RESET_TASK_IF_NEEDED包含:

如果设置,并且此活动要么在新任务中启动,要么将现有任务置于顶部,那么它将作为任务的前门启动.这将导致应用任务所需的任何关联性,以使该任务处于适当的状态(将活动移入或移出),或者仅在需要时将该任务重置为其初始状态.

那不是特别清楚.

特别是,它似乎是相同的效果将使用的组合可以看出FLAG_ACTIVITY_CLEAR_TOPFLAG_ACTIVITY_SINGLE_TOP.引用文档FLAG_ACTIVITY_CLEAR_TOP:

如果已设置,并且正在启动的活动已在当前任务中运行,则不会启动该活动的新实例,而是将关闭其上的所有其他活动,并将此Intent传递给(现在开启) top)旧活动作为一个新的意图......

当前运行的[所需活动]实例将在其onNewIntent()方法中接收您从此处开始的新意图,或者本身已完成并使用新意图重新启动.如果它已将其启动模式声明为"多个"(默认值)并且您没有在同一意图中设置FLAG_ACTIVITY_SINGLE_TOP,那么它将被完成并重新创建; 对于所有其他启动模式或如果设置了FLAG_ACTIVITY_SINGLE_TOP,则此Intent将被传递到当前实例的onNewIntent().

FLAG_ACTIVITY_CLEAR_TOP文档是有道理的,至少对我来说.

那么,这FLAG_ACTIVITY_RESET_TASK_IF_NEEDEDFLAG_ACTIVITY_CLEAR_TOPand 的组合FLAG_ACTIVITY_SINGLE_TOP有何不同?


如果您可以解释FLAG_ACTIVITY_CLEAR_TASK与上述其他两个选项中的任何一个不同的加分点.

如果在传递给Context.startActivity()的Intent中设置,则此标志将导致在活动开始之前清除与活动关联的任何现有任务.也就是说,活动成为否则为空任务的新根,并且任何旧活动都已完成.这只能与FLAG_ACTIVITY_NEW_TASK一起使用.

这和FLAG_ACTIVITY_CLEAR_TOP| 之间有一个明显的区别 FLAG_ACTIVITY_SINGLE_TOPFLAG_ACTIVITY_CLEAR_TASK需要的FLAG_ACTIVITY_NEW_TASK.但是,除此之外,看起来净效果是相同的,也是匹配的FLAG_ACTIVITY_RESET_TASK_IF_NEEDED.

Dav*_*ser 41

我看了一下源代码ActivityManager.该标志Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED确实做了一些不做的魔法Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP:它触发任务重新定位.

这是一个(虽然很蹩脚)的例子:

在App A中,我们有root活动RootA,我们有另一个Activity ReparentableA:

<application
        android:label="@string/app_name">
    <activity android:name=".RootA">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
    <activity android:name=".ReparentableA"
            android:allowTaskReparenting="true"/>
</application>
Run Code Online (Sandbox Code Playgroud)

App A的包名称为"com.app.a",因此taskAffinity其组件的默认值为"com.app.a".

在App B中,我们有root活动RootB:

<application
        android:label="@string/app_name">
    <activity android:name="RootB">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
</application>
Run Code Online (Sandbox Code Playgroud)

应用B的包名称为"com.app.b",因此taskAffinity其组件的默认值为"com.app.b".

现在我们从HOME屏幕启动App B. 这将启动一个新任务,并创建一个新的Activity实例RootB作为该任务中的根Activity.Activity RootB现在ReparentableA以标准方式启动Activity ,没有任何特殊标志.ReparentableA创建一个实例并将其置于RootB当前任务的顶部.

按HOME.

现在我们从HOME屏幕启动App A. 这将启动一个新任务,并创建一个新的Activity实例RootA作为该任务中的根Activity.注意:当Android启动"启动器"意图时,它会自动设置标志Intent.FLAG_ACTIVITY_NEW_TASKIntent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED.因此,启动RootA现在会触发任务重新创建.Android会查看是否有任何其他任务中的任何活动与此新任务具有相关性(并且是可重新定位的).它在App B任务中找到ReparentableA(具有RootA与之相同的任务关联性)并将其移动到新的App A任务.在启动App A时,我们看不到RootA,我们实际看到ReparentableA,因为它被移动到新任务的顶部.

如果我们返回App B,我们可以看到它ReparentableA已从任务堆栈中消失,而且该任务现在只包含一个Activity : RootB.


使用注意事项 Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP

使用这些标志"重置任务"时要记住的重要一点是,只有在任务的根目录中已经存在目标Activity的实例时,它才有效.如果您的root活动完成,则无法通过启动root活动来清除您的任务Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP.Android将只创建一个目标(root)Activity的新实例,并将其置于任务中的现有活动之上,这可能根本不是你想要的.


Intent.FLAG_ACTIVITY_CLEAR_TASK和之间的区别Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP:

如上所述,CLEAR_TOP | SINGLE_TOP仅在任务中已存在目标活动的实例时才使用.CLEAR_TASK但是,无论任务中是否存在目标活动的实例,都会从任务中删除所有活动.此外,使用CLEAR_TASK确保目标活动成为任务的根活动,而无需在清除任务之前知道什么活动是根活动.


Intent.FLAG_ACTIVITY_CLEAR_TASK和之间的区别Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED:

如上所述,使用CLEAR_TASK始终从任务中删除所有活动并启动目标活动的新实例.相反,RESET_TASK_IF_NEEDED只会在某些情况下重置任务("IF_NEEDED"部分).如果Android是以下任务,则任务仅"重置":

  • 创建一个新任务(在这种情况下,"重置"功能涉及上面解释的任务重新定义),或
  • 如果Android将后台任务带到前台(在这种情况下,任务仅清除任何已启动的Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET活动以及这些活动之上的任何活动).注意:在这种情况下,根活动永远不会被清除.

重要说明:在测试时,请注意Android在从HOME屏幕(或可用应用程序列表)启动应用程序时以及从最近任务列表中选择任务时的行为方式有所不同.

在第一种情况(通过从可用应用程序的列表或从快捷方式在HOME画面上选择它启动一个应用程序),一个发射器IntentIntent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED被创建.无论应用程序是否已在运行,都会使用此选项.该Intent启动,然后ActivityManager计算出该怎么做.

在第二种情况下(从最近任务列表中选择一个任务),如果任务仍然存在,那么它就会被带到前面.如果使用最近的任务列表将任务放在前面,则不执行任务"重置".对我来说这是如何管理的并不是很明显,我也没有机会查看源代码以找出原因.


我希望这回答了你的问题.期待您的反馈和测试结果.

  • 非常感谢!我将在周末进行一些与此相关的测试. (2认同)