launchMode affinity allowTaskReparent

来源:互联网 发布:windows 垃圾清理 编辑:程序博客网 时间:2024/05/22 03:17

Task BackStack

Task是指当用户处理一项具体事务时,与用户交互的一系列Activity,而这些Activity按顺序(先进后出)存放在BackStack中.用户从launcher(首页)点击一个icon开始一个app时,如果这时没有一个对应的task,那系统就会创建一个task,app中被打上<action android:name="android.intent.action.MAIN"/> 的activity将位于BackStack的底部.

affinity

个人觉得像task id,一般与launchMode,allowReparent一起使用,由android:taskAffinity决定.
<activity android:taskAffinity="">默认和<application android:taskAffinity="">中的一样,若application未制定,使用<manifest package="">.默认情况下,application下的activity拥有相同的affinity.

launchMode

参考:http://inthecheesefactory.com/blog/understand-android-activity-launchmode/en
launchMode分为四种:
1. standard
2. singleTop
3. singleTask
4. singleInstance
standard和singleTop都是加入到启动它的Activity所在task的BackStack中.
standard

区别在于,如果一个singleTop的Activity A在启动它的task的顶部,再次启动A不会创建新的实例,而是调用 A的onNewIntent方法.
singleTop

若调用者是其他app,在5.0前同上.
调用者为其他app

5.0及之后,参照的log中说:会把Activity放在一个新的task,但是写了个demo在6.0和5.0上都试了下,表现都是5.0前一样.
这里写图片描述

singleTask和singleInstance:一个launchMode为singleTask和singleInstance的Activity,在系统中只有一个实例.

singleTask:启动一个launchMode为singleTask的Activity A,若A未存在,则在调用者的task上加入一个Activity A.
singleTask

但是若在task中已经存在A,不再创建,触发A.onNewIntent.并且在此Activity A上的Activity全部销毁,会调用相应的生命周期.
singleTask,如果已经存在
你可能会注意到在Android文档中提到:

The system creates a new task and instantiates the activity at the root of the new task.
但是并不像所描述的一样.而是像前文所述.

Task id #239  TaskRecord{428efe30 #239 A=com.thecheesefactory.lab.launchmode U=0 sz=2}  Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.thecheesefactory.lab.launchmode/.StandardActivity }    Hist #1: ActivityRecord{429a88d0 u0 com.thecheesefactory.lab.launchmode/.SingleTaskActivity t239}      Intent { cmp=com.thecheesefactory.lab.launchmode/.SingleTaskActivity }      ProcessRecord{42243130 18965:com.thecheesefactory.lab.launchmode/u0a123}    Hist #0: ActivityRecord{425fec98 u0 com.thecheesefactory.lab.launchmode/.StandardActivity t239}      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.thecheesefactory.lab.launchmode/.StandardActivity }      ProcessRecord{42243130 18965:com.thecheesefactory.lab.launchmode/u0a123}

除非你设置了affinity:

<activity    android:name=".SingleTaskActivity"    android:label="singleTask launchMode"    android:launchMode="singleTask"    android:taskAffinity="">

如果调用者是其他app,启动一个launchMode为singleTask的Activity A不存在,并且A所指定taskAffinity的task T也不存在.则创建一个task.而不像上面直接在task中加一个.
singleTask other App

若A所指定taskAffinity的Task #1存在,并且BackStack状态为:[Activity B(已存在)],Activity A不存在.则恢复Task #1,并将Activity A加入到Task #1的顶部.BackStack状态为:[Activity B -> Activity A].按下back键,先回到Activity B,再按下back键返回Task #1.
这里写图片描述

若A所指定taskAffinity的Task #1存在,并且ActivityA也存在.BackStack状态为:[ActivityB -> Activity A -> Activity B -> Activity B].则恢复Task #1,并将Activity A上的所有Activity销毁,其他同上.
这里写图片描述

singleInstance和singleTask很像,唯一不同是,持有singleInstance activity的Task,BackStack里只会有这一个Activity.
这里写图片描述
如上图,当有两个Task时,只有一个Task会显示在TaskManager里
这里写图片描述
Task#1 -> 启动singleInstance的Activity(Task# 2),按下Home键,显示TaskManager,此时只有Task#2在TaskManager里显示,点击Task#2恢复,点击back.直接返回Launcher.(没有经过Task#1)
Task#1 -> 启动singleInstance的Activity(Task# 2),按下Home键,点击Launcher的Icon,进入Task#1.按下返回,直到Task#1里的Activity全部弹出后,直接返回Launcher.(没有经过Task#2)
此问题可以通过设置affinity来解决.

Intent Flags

除了在manifest中制定launchMode,我们也可以通过指定IntentFlags来达到相应的效果

allowTaskReparent

最后说说allowTaskReparent.以下是文档中的解释:

Whether or not the activity can move from the task that started it to the task it has an affinity for when that task is next brought to the front — “true” if it can move, and “false” if it must remain with the task where it started.

Activity是否可以从创建他的task #1,移动到该Activity所指定的affinity的task #2,当task #2再次到前台的时候.true:可以移动,false:不可以,必须保留在创建他的task #1.
写了个Demo,试了一下:
1.Launcher点击App#1的icon开启一个Task #1,将Activity A置于Task #1的BackStack.
2.在Activity A中启动 App #2: Activity B.此时A和B都在Task #1中.
3.按下Home返回Launcher.此时TaskManager为:
这里写图片描述
4.点击App#2的icon开启一个Task #2:将Activity C置于Task #2的BackStack.由于Activity B属于Task #2(默认情况详细请看前文关于affinity),并且设置了allowReparent为true,所以将Activity B移动至Task #2.
Task #2 BackStack状态为:[Activity C->Activity B].Task #2 BackStack状态为:[Activity A]
下图为App #2 AndroidManifest的代码片段:

<application    android:name="app2"    ....<activity    android:name=".ActivityC"    android:label="@string/app_name"    android:theme="@style/AppTheme.NoActionBar">    <intent-filter>        <action android:name="android.intent.action.MAIN"/>        <category android:name="android.intent.category.LAUNCHER"/>    </intent-filter></activity>...<activity    android:name=".ActivityB"    android:allowTaskReparenting="true">    <intent-filter>        <action android:name="com.azu.demo.Affinity"/>        <category android:name="android.intent.category.DEFAULT"/>    </intent-filter></activity></application>

若有错误请评论

0 0
原创粉丝点击