讲讲Android的launchMode,taskAffinity,以及Intent Flags

站在巨人的肩膀上

  1. Android总结篇系列:Activity Intent FlagsTask相关属性
  2. Android中的Affinity(各种Intent Flag以及Activity manifest特性讲解)
  3. ActivityRecord、TaskRecord、ActivityStack

理解 + 总结

  1. 结论:
    • 如果ActivitylaunchModestandardsingleTop,那么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设置了taskAffinityhello.everyone,但它还是放在和ActivityA一致的hello.worldtask中,说明在上述情况中,设置taskAffinity无效.ActivityC同理.

  1. 结论:
    • 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

  1. 结论:
    • luanchModesingleTask或者设置Intent.FLAG_ACTIVITY_NEW_TASK的时候,系统会寻找新的task来存放目标Activity,寻找是依据目标ActivitytaskAffinity属性进行匹配,找不到就新建task然后放入.

    • 如果只设置了singleTask或者Intent.FLAG_ACTIVITY_NEW_TASK,没有设置taskAffinity,那么该Activity会沿用ApplicationtaskAffinity,而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}
      
      
  1. 结论:
    • 在如上结论的基础上,新的Activity设置singleTask后,并不一定会添加到已存在的相同taskAffinitytask中,如果相同taskAffinitytasksingleInstance的,那么会新建同名taskAffinitytask,然后放入.

      准备条件:
          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}
      
      

      由上述可知,ActivityCtaskAffinity虽然和ActivityB一致,但是因为ActivityBsingleInstance,所以ActivityC添加不到ActivityB所在的task中,ActivityC只能新建一个taskAffinity也是hello.every的不同的task.

  1. 什么时候会将目标Activity放置到新task中?

    1. 目标ActivitylaunchMode设置为singleInstance的时候.
    2. 目标ActivitylaunchMode设置为singleTask,同时设置目标ActivitytaskAffinity不同于启动它的Activity
    3. 欢迎补充……
  2. launchModeIntent Flag

    • singleTop = FLAG_ACTIVITY_SINGLE_TOP
    • singleTask = FLAG_ACTIVITY_CLEAR_TOP + FLAG_ACTIVITY_SINGLE_TOP
  3. android:noHistory

    • 错误理解: 具有此属性标识的Activity当导航到其他Activity上时,Activity栈将不记录其自身. — ❌

    • 正确理解: 当当前Activity标记为noHistory时,跳转到其他Activity时,当前Activity被标记为finishing,并不会马上调用onDestory方法,它会在合适的时候调用onDestory.✅

    • 上面”合适的时候”有:当这个Activity再次回到前台时,用户点击”Home”键时……欢迎补充,欢迎打脸

    • 所以: 标记noHistoryActivity很有可能会导致回收不及时而引起内存问题. 👈👈👈

      准备条件:
          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}
      
      
      
    原文作者:画十
    原文地址: https://www.jianshu.com/p/a0d93dc6bca5
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞