站在巨人的肩膀上
Android总结篇系列:Activity Intent Flags及Task相关属性Android中的Affinity(各种Intent Flag以及Activity manifest特性讲解)ActivityRecord、TaskRecord、ActivityStack
理解 + 总结
-
结论:
-
如果
Activity的launchMode是standard或singleTop,那么taskAffinity设置无效,该Activity会跟随启动它的Activity一致的affinity准备条件: ActivityA: android:launchMode="standard" android:taskAffinity="hello.world" ActivityB: android:launchMode="standard" android:taskAffinity="hello.everyone" ActivityB: android:launchMode="singleTop" android:taskAffinity="hello.everybody" 步骤: 打开ActivityA -> startActivity到ActivityB -> startActivity到ActivityC 结果:(adb shell dumpsys activity) Stack #40: type=standard mode=fullscreen Running activities (most recent first): TaskRecord{fae42ac #403 A=hello.world U=0 StackId=40 sz=3} Run #2: ActivityRecord{d2989ab u0 com.example.hurshi.app_a/.AppA_ActivityC t403} Run #1: ActivityRecord{62cf49f u0 com.example.hurshi.app_a/.AppA_ActivityB t403} Run #0: ActivityRecord{93b3122 u0 com.example.hurshi.app_a/.AppA_ActivityA t403}由上述实验可知,虽然
ActivityB设置了taskAffinity为hello.everyone,但它还是放在和ActivityA一致的hello.world的task中,说明在上述情况中,设置taskAffinity无效.ActivityC同理.
-
-
结论:
-
taskAffinity并不是task的唯一编号,允许不同task拥有相同的taskAffinity准备条件: ActivityA: android:launchMode="singleInstance" android:taskAffinity="hello.world" ActivityB: android:launchMode="singleInstance" android:taskAffinity="hello.world" 步骤: 打开ActivityA -> startActivity到ActivityB 结果: Stack #12: type=standard mode=fullscreen Running activities (most recent first): TaskRecord{783509b #348 A=hello.world U=0 StackId=12 sz=1} Run #0: ActivityRecord{eeea074 u0 com.example.hurshi.app_a/.AppA_ActivityB t348} Stack #11: type=standard mode=fullscreen Running activities (most recent first): TaskRecord{85abc38 #347 A=hello.world U=0 StackId=11 sz=1} Run #0: ActivityRecord{4f6d2db u0 com.example.hurshi.app_a/.AppA_ActivityA t347}由上述
ActivityA,ActivityB可以看出,他们的taskAffinity是一致的,但是它们的stackId是不一致的,由此可知:taskAffinity并不是task的唯一编号,允许不同task拥有相同的taskAffinity
-
-
结论:
当
luanchMode为singleTask或者设置Intent.FLAG_ACTIVITY_NEW_TASK的时候,系统会寻找新的task来存放目标Activity,寻找是依据目标Activity的taskAffinity属性进行匹配,找不到就新建task然后放入.-
如果只设置了
singleTask或者Intent.FLAG_ACTIVITY_NEW_TASK,没有设置taskAffinity,那么该Activity会沿用Application的taskAffinity,而Application的默认taskAffinity是包名准备条件: Application: android:taskAffinity="com.application" ActivityA: android:launchMode="standard" android:taskAffinity="hello.world" ActivityB: android:launchMode="singleTask" android:taskAffinity="hello.everyone" 步骤: 打开ActivityA -> startActivity到ActivityB 结果: Stack #38: type=standard mode=fullscreen Running activities (most recent first): TaskRecord{7ff1d1c #401 A=com.application U=0 StackId=38 sz=1} Run #0: ActivityRecord{ecb9efb u0 com.example.hurshi.app_a/.AppA_ActivityB t401} Stack #37: type=standard mode=fullscreen Running activities (most recent first): TaskRecord{2261d25 #400 A=hello.world U=0 StackId=37 sz=1} Run #0: ActivityRecord{4b36f0f u0 com.example.hurshi.app_a/.AppA_ActivityA t400}
-
结论:
-
在如上结论的基础上,新的
Activity设置singleTask后,并不一定会添加到已存在的相同taskAffinity的task中,如果相同taskAffinity的task是singleInstance的,那么会新建同名taskAffinity的task,然后放入.准备条件: ActivityA: android:launchMode="standard" android:taskAffinity="hello.world" ActivityB: android:launchMode="singleInstance" android:taskAffinity="hello.everyone" ActivityC: android:launchMode="singleTask" android:taskAffinity="hello.everyone" 步骤: 打开ActivityA -> startActivity到ActivityB -> startActivity到ActivityC 结果: Stack #17: type=standard mode=fullscreen Running activities (most recent first): TaskRecord{a26014f #353 A=hello.everyone U=0 StackId=17 sz=1} Run #0: ActivityRecord{358157e u0 com.example.hurshi.app_a/.AppA_ActivityC t353} Stack #16: type=standard mode=fullscreen Running activities (most recent first): TaskRecord{6c18ba #352 A=hello.everyone U=0 StackId=16 sz=1} Run #0: ActivityRecord{68f9e46 u0 com.example.hurshi.app_a/.AppA_ActivityB t352} Stack #15: type=standard mode=fullscreen Running activities (most recent first): TaskRecord{8aed0dc #351 A=hello.world U=0 StackId=15 sz=1} Run #0: ActivityRecord{a37e4a8 u0 com.example.hurshi.app_a/.AppA_ActivityA t351}由上述可知,
ActivityC的taskAffinity虽然和ActivityB一致,但是因为ActivityB是singleInstance,所以ActivityC添加不到ActivityB所在的task中,ActivityC只能新建一个taskAffinity也是hello.every的不同的task.
-
-
什么时候会将目标
Activity放置到新task中?- 目标
Activity的launchMode设置为singleInstance的时候. - 目标
Activity的launchMode设置为singleTask,同时设置目标Activity的taskAffinity不同于启动它的Activity - 欢迎补充......
- 目标
-
launchMode和Intent Flag-
singleTop=FLAG_ACTIVITY_SINGLE_TOP -
singleTask=FLAG_ACTIVITY_CLEAR_TOP+FLAG_ACTIVITY_SINGLE_TOP
-
-
android:noHistory错误理解:
具有此属性标识的--- ❌Activity当导航到其他Activity上时,Activity栈将不记录其自身.正确理解: 当当前
Activity标记为noHistory时,跳转到其他Activity时,当前Activity被标记为finishing,并不会马上调用onDestory方法,它会在合适的时候调用onDestory.✅上面"合适的时候"有:当这个
Activity再次回到前台时,用户点击"Home"键时......欢迎补充,欢迎打脸-
所以: 标记
noHistory的Activity很有可能会导致回收不及时而引起内存问题. 👈👈👈准备条件: ActivityA: ActivityB: android:noHistory="true" ActivityC: 步骤1: 打开ActivityA -> startActivity到ActivityB -> startActivity到ActivityC 结果1: Stack #54: type=standard mode=fullscreen Running activities (most recent first): TaskRecord{26b634f #418 A=com.application U=0 StackId=54 sz=3} Run #2: ActivityRecord{444fa10 u0 com.example.hurshi.app_a/.AppA_ActivityC t418} //最后的 "f" 标记表示 "finishing" Run #1: ActivityRecord{5c65974 u0 com.example.hurshi.app_a/.AppA_ActivityB t418 f} Run #0: ActivityRecord{d4ac684 u0 com.example.hurshi.app_a/.AppA_ActivityA t418} 步骤2: 按 back 键 结果2: Stack #54: type=standard mode=fullscreen Running activities (most recent first): TaskRecord{26b634f #418 A=com.application U=0 StackId=54 sz=1} Run #0: ActivityRecord{d4ac684 u0 com.example.hurshi.app_a/.AppA_ActivityA t418}