android:allowTaskReparenting
在App A中,我们有根ActivityRootA
和另外一个ActivityReparentableA
<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>
App A的包名是com.app.a
,所以默认的taskAffinity
就是com.app.a
在App B中,我们有根ActivityRootB
<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>
现在我们从桌面打开App B。这会开启新的Task,并在Task中创建新的Activity实例RootB
作为根Activity。从RootB
Activity中使用标准Intent启动ReparentableA
,没有指定任何Flags。ReparentableA
的一个实例将会被创建并放置到RootB的顶部。
点击Home
键
现在我们从桌面启动App A,这次启动将会创建一个新的Task和新的Activity(RootA
)实例。RootA
作为根Activity。
注:当Android启动一个lacuncher
Intent,它将会自动设置flagsIntent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
。因为这个原因,Root
的启动将会触发
ATask Reparenting
。此时,Android查找所有其他的Task,如果有Activity拥有与当前Task相同affinity
属性,并且android:allowTaskReparenting="true"
,它会发现ReparentableA
在App B的Task中,然后移动ReparentableA
到App A的Task底部(这里是在RootA
的顶部
)。所以我们将会看到ReparentableA
。如果我们回到App B中,我们会发现,ReparentableA
消失了,仅剩下RootB
注意
Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP
使用Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP
来清除一个Task,仅仅工作在已经存在一个目标Activity的实例在Task的底部(root),如果Task底部的Activity已经被清除,你将不能通过启动底部的Activity来清除Task.Android仅仅会创建一个新的目标实例在Task的顶部,这可能不是你想要的。Intent.FLAG_ACTIVITY_CLEAR_TASK
和Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP
的不同
正如前面提到的,CLEAR_TOP | SINGLE_TOP
仅仅工作在已经有一个目标Activity实例存在Task。CLEAR_TASK
会清除掉所有在Task中的activity,并重新创建一个新的实例,而不管要启动的activity是否已经存在在Task中。最终,目标activity必定存在于Task的底部。Intent.FLAG_ACTIVITY_CLEAR_TASK
和Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
的不同
CLEAR_TASK
总是会清除Task,而RESET_TASK_IF_NEEDED
只会在下面情况下,清除Task
- 创建新的Task(在这种情况下,设置了
taskreparent
属性为true的Activity将会被置于新Task的顶部 - 如果android将后台Task转换为前台Task(在这种情况下,这个Task仅仅清除以
Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
启动的Activity,以及任何在这些Activity之上的Activity。)注:底部的Activity永远不会被清除,在这种情况下。
- 创建新的Task(在这种情况下,设置了
singleTask
与FLAG_ACTIVITY_NEW_TASK
区别
singleTask
启动的Activity,系统会先判断对应的标识为taskAffinity
的Task是否存在,如果存在则查看该Task中是否有该Activity实例,如果有,则将该activity上的所有其他的activity清除,使得启动的activity在Task顶部。如果没有该Activity实例,就创建一个。总之就是保证在对应的Task中唯一。singleInstance
全局唯一
FLAG_ACTIVITY_NEW_TASK
与taskAffinity
一起使用。保证在对应的taskAffinity
Task中唯一,如果已经存在则什么都不做(搭配FLAG_ACTIVITY_CLEAR_TOP
可以清除该activity之上的其他activity),如果不存在则创建该Activity