解决Android App 每启动一个Activity就看上去多启动一个应用/进程的问题 ...

一给  金牌会员 | 2022-6-24 11:36:05 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 542|帖子 542|积分 1626

背景

出现一个很神奇的问题,集成了一个library依赖后,每启动一个FLAG_ACTIVITY_NEW_TASK标志位的Activity就会在任务管理器中多一个"应用"。
如果去除这个library依赖,则无论启动多少个带FLAG_ACTIVITY_NEW_TASK标志位的Activity,任务管理器中永远都只有这一个"应用"。
重现步骤

我们依赖了该library库,然后启动了3个带FLAG_ACTIVITY_NEW_TASK标志位的activity,MainActivity->SecondActivity->ThirdActivity
  1. val intent = Intent(MainActivity@ this, SecondActivity::class.java)
  2. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
  3. startActivity(intent)
复制代码
我们打开任务管理器,可以看到如下效果

如果,我们去除该library的依赖,打开任务管理器,就只会有一个"应用"。
或者去除启动Activity时的FLAG_ACTIVITY_NEW_TASK标志,也只会有一个应用。

原因

后来,排查后,发现和taskAffinity有关。
原来,在该library中,我们在AndroidManifest.xml的Application节点 添加了一个android:taskAffinity="",导致了这个问题。
去掉这个值就不会有这个问题了。
taskAffinity

taskAffinity我们平时很少去用它,它的作用是什么呢 ?
查阅了资料可知
是用于在启动activity时,指定activity放入哪个task (指定想要的任务栈)
官网文档上关于taskAffinity的说明 : https://developer.android.google.cn/guide/topics/manifest/activity-element#lmode

我们来做下试验
试验一

我们保留android:taskAffinity="",启动了3个带FLAG_ACTIVITY_NEW_TASK标志位的activity,MainActivity->SecondActivity->ThirdActivity,可以看到任务管理器里有3个"应用"

我们使用adb命令,查看下当前Activity栈的信息
  1. adb shell  dumpsys activity activities
复制代码
我们搜索Stack #,可以看到如下信息
  1.   Stack #384: type=standard mode=fullscreen
  2.   isSleeping=false
  3.   mBounds=Rect(0, 0 - 0, 0)
  4.     mLastPausedActivity: ActivityRecord{18aa8f u0 com.heiko.mytest0614/.ThirdActivity t384}
  5.     * Task{812611c #384 visible=true type=standard mode=fullscreen translucent=true I=com.heiko.mytest0614/.ThirdActivity U=0 StackId=384 sz=1}
  6.       ...省略...
  7.           taskAffinity=null
  8.           ...省略...
  9.   Stack #383: type=standard mode=fullscreen
  10.   isSleeping=false
  11.   mBounds=Rect(0, 0 - 0, 0)
  12.     mLastPausedActivity: ActivityRecord{84c8851 u0 com.heiko.mytest0614/.SecondActivity t383}
  13.     * Task{9c4e8b6 #383 visible=true type=standard mode=fullscreen translucent=true I=com.heiko.mytest0614/.SecondActivity U=0 StackId=383 sz=1}
  14.       ...省略...
  15.           taskAffinity=null
  16.           ...省略...
  17.   Stack #382: type=standard mode=fullscreen
  18.   isSleeping=false
  19.   mBounds=Rect(0, 0 - 0, 0)
  20.     mLastPausedActivity: ActivityRecord{c88411e u0 com.heiko.mytest0614/.MainActivity t382}
  21.     * Task{50f0dff #382 visible=true type=standard mode=fullscreen translucent=true I=com.heiko.mytest0614/.MainActivity U=0 StackId=382 sz=1}
  22.           ...省略...
  23.       taskAffinity=null
  24.           ...省略...
复制代码
com.heiko.mytestApp项目,拥有3个任务栈,且taskAffinity都是null。
试验二

我们去除android:taskAffinity="",启动了3个带FLAG_ACTIVITY_NEW_TASK标志位的activity,MainActivity->SecondActivity->ThirdActivity,可以看到任务管理器里有1个"应用"

我们使用adb命令,查看下当前Activity栈的信息
  1. adb shell  dumpsys activity activities
复制代码
我们搜索Stack #,可以看到如下信息
  1. ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
  2. Display #0 (activities from top to bottom):
  3.   Stack #424: type=standard mode=fullscreen
  4.   isSleeping=false
  5.   mBounds=Rect(0, 0 - 0, 0)
  6.     mResumedActivity: ActivityRecord{66c8f u0 com.heiko.mytest0614/.ThirdActivity t424}
  7.     mLastPausedActivity: ActivityRecord{66c8f u0 com.heiko.mytest0614/.ThirdActivity t424}
  8.     * Task{813f21d #424 visible=true type=standard mode=fullscreen translucent=true A=10314:com.heiko.mytest0614 U=0 StackId=424 sz=3}
  9.       ...省略
  10. supportsSplitScreenWindowingMode=true      lastActiveTime=1806671486 (inactive for 7s)
  11. pcFlags 0      * Hist #2: ActivityRecord{66c8f u0 com.heiko.mytest0614/.ThirdActivity t424}
  12.           packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
  13.           ...省略...
  14.           taskAffinity=10314:com.heiko.mytest0614
  15.           ...省略...
  16.       * Hist #1: ActivityRecord{7a80a7 u0 com.heiko.mytest0614/.SecondActivity t424}
  17.           packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
  18.           ...省略...
  19.           taskAffinity=10314:com.heiko.mytest0614
  20.           ...省略...
  21.       * Hist #0: ActivityRecord{870bb65 u0 com.heiko.mytest0614/.MainActivity t424}
  22.           packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
  23.           ...省略...
  24.           taskAffinity=10314:com.heiko.mytest0614
  25.           ...省略...
复制代码
com.heiko.mytestApp项目,拥有1个任务栈,这个栈里有三个ActivityRecord,且taskAffinity都是10314:com.heiko.mytest0614
试验三

我们去除android:taskAffinity="",ThirdActivity的taskAffinity设置为com.heiko.third,启动了3个带FLAG_ACTIVITY_NEW_TASK标志位的activity,MainActivity->SecondActivity->ThirdActivity,可以看到任务管理器里有2个"应用"

我们使用adb命令,查看下当前Activity栈的信息
  1. adb shell  dumpsys activity activities
复制代码
我们搜索Stack #,可以看到如下信息
  1. ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
  2. Display #0 (activities from top to bottom):
  3.   Stack #437: type=standard mode=fullscreen
  4.   isSleeping=false
  5.   mBounds=Rect(0, 0 - 0, 0)
  6.     mResumedActivity: ActivityRecord{2d1e033 u0 com.heiko.mytest0614/.ThirdActivity t437}
  7.     * Task{1e2ff0 #437 visible=true type=standard mode=fullscreen translucent=true A=10314:com.heiko.third U=0 StackId=437 sz=1}
  8.       ...省略...
  9. supportsSplitScreenWindowingMode=true      lastActiveTime=1807455552 (inactive for 2s)
  10. pcFlags 0      * Hist #0: ActivityRecord{2d1e033 u0 com.heiko.mytest0614/.ThirdActivity t437}
  11.           packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
  12.           ...省略...
  13.           taskAffinity=10314:com.heiko.third
  14.           ...省略...
  15.   Stack #436: type=standard mode=fullscreen
  16.   isSleeping=false
  17.   mBounds=Rect(0, 0 - 0, 0)
  18.     mLastPausedActivity: ActivityRecord{2197e45 u0 com.heiko.mytest0614/.SecondActivity t436}
  19.     * Task{2384575 #436 visible=true type=standard mode=fullscreen translucent=true A=10314:com.heiko.mytest0614 U=0 StackId=436 sz=2}
  20.       ...省略...
  21. supportsSplitScreenWindowingMode=true      lastActiveTime=1807455438 (inactive for 2s)
  22. pcFlags 0      * Hist #1: ActivityRecord{2197e45 u0 com.heiko.mytest0614/.SecondActivity t436}
  23.           packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
  24.           ...省略...
  25.           taskAffinity=10314:com.heiko.mytest0614
  26.           ...省略...
  27.       * Hist #0: ActivityRecord{bfa74ac u0 com.heiko.mytest0614/.MainActivity t436}
  28.           packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
  29.           ...省略...
  30.           taskAffinity=10314:com.heiko.mytest0614
  31.           ...省略...
复制代码
com.heiko.mytestApp项目,拥有2个任务栈。
Stack #437任务栈里有一个ActivityRecord,taskAffinity为10314:com.heiko.third,
Stack #436任务栈里有两个ActivityRecord,taskAffinity为10314:com.heiko.mytest0614
试验四

我们去除android:taskAffinity="",ThirdActivity的launchMode设置为singleInstance,启动了3个带FLAG_ACTIVITY_NEW_TASK标志位的activity,MainActivity->SecondActivity->ThirdActivity,可以看到任务管理器里有1个"应用"

我们使用adb命令,查看下当前Activity栈的信息
  1. adb shell  dumpsys activity activities
复制代码
我们搜索Stack #,可以看到如下信息
  1. ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
  2. Display #0 (activities from top to bottom):
  3.   Stack #434: type=standard mode=fullscreen
  4.   isSleeping=false
  5.   mBounds=Rect(0, 0 - 0, 0)
  6.     mResumedActivity: ActivityRecord{e1a6f04 u0 com.heiko.mytest0614/.ThirdActivity t434}
  7.     * Task{2caced #434 visible=true type=standard mode=fullscreen translucent=true A=10314:com.heiko.mytest0614 U=0 StackId=434 sz=1}
  8.       ...省略...
  9. pcFlags 0      * Hist #0: ActivityRecord{e1a6f04 u0 com.heiko.mytest0614/.ThirdActivity t434}
  10.           packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
  11.           ...省略...
  12.           taskAffinity=10314:com.heiko.mytest0614
  13.           ...省略...
  14.                   
  15.                   
  16. Stack #433: type=standard mode=fullscreen
  17.   isSleeping=false
  18.   mBounds=Rect(0, 0 - 0, 0)
  19.     mLastPausedActivity: ActivityRecord{8551b41 u0 com.heiko.mytest0614/.SecondActivity t433}
  20.     * Task{4450b31 #433 visible=true type=standard mode=fullscreen translucent=true A=10314:com.heiko.mytest0614 U=0 StackId=433 sz=2}
  21.       ...省略...
  22. supportsSplitScreenWindowingMode=true      lastActiveTime=1807157149 (inactive for 2s)
  23. pcFlags 0      * Hist #1: ActivityRecord{8551b41 u0 com.heiko.mytest0614/.SecondActivity t433}
  24.           packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
  25.           ...省略...
  26.           taskAffinity=10314:com.heiko.mytest0614
  27.           ...省略...
  28.       * Hist #0: ActivityRecord{ec9ff65 u0 com.heiko.mytest0614/.MainActivity t433}
  29.           packageName=com.heiko.mytest0614 processName=com.heiko.mytest0614
  30.           ...省略...
  31.           taskAffinity=10314:com.heiko.mytest0614
  32.           ...省略...
复制代码
com.heiko.mytestApp项目,拥有2个Activity栈,Stack #433任务栈里有两个ActivityRecord,Stack #434栈中有一个ActivityRecord,且taskAffinity都是10314:com.heiko.mytest0614
小结



  • taskAffinity的不同,直观的表现是在任务管理器里,以不同的"应用"来体现
  • 微信的每一个小程序,都在任务管理器里单独显示,也是用到了taskAffinity
  • taskAffinity一样的Activity具有同一任务 (从用户的角度来看,则是归属同一"应用")
  • 默认情况下,应用中的所有 Activity的taskAffinity 都一样,为应用的包名
  • 如要要指定 Activity 与任何任务都不一样,需将其设置为空字符串
  • 不仅可以给同一个应用的不同activity设置不同的affinity,也可以给不同应用的activity设置相同的affinity,使它们在用户角度看来好像属于同一个应用
  • 当启动模式设置为 standard 或 singleTop 时,taskAffinity是不起作用的,待启动的 Activity 会跟随 源Activity 的任务栈,即使你显式声明了不一样的 taskAffinity
  • 当启动模式设置了 singleTask 或者 singleInstance 时,它就会新建任务栈来存储待启动的 Activity 实例
  • 除了 singleTask 和 singleInstance 以外,FLAG_ACTIVITY_NEW_TASK 也会使 taskAffinity 生效
   在不设置 taskAffinity 的情况下,单独设置 FLAG_ACTIVITY_NEW_TASK 并没有任何意义,不会创建新的任务栈
FLAG_ACTIVITY_NEW_TASK 更被大家所熟知的用法可能是 从非 Activity 环境启动 Activity 。
默认情况下,待启动的 Activity 会进入源 Activity 所在的任务栈中。如果是从 非 Activity 环境启动,例如 Service,Broadcast,Application 等,根本不存在与之对应的任务栈,AMS 无从推断该把 Activity 放入哪个任务栈,就会抛出异常 Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag
    对于非 Activity 启动的 Activity需要显示的设置 FLAG_ACTIVITY_NEW_TASK,而singleTask 及 singleInstance 在 AMS 中被预处理后,隐形的设置了 FLAG_ACTIVITY_NEW_TASK,而启动模式是 standard 及 singletTop 的 Activity 不会被设置 FLAG_ACTIVITY_NEW_TASK,除非通过显式的 Intent setFlag() 进行设置。
FLAG_ACTIVITY_NEW_TASK 这个属性更多的关注点是在 Task,可以认为没有设置 FLAG_ACTIVITY_NEW_TASK 的情况下,taskAffinity 可以不考虑。
  其他

   参考
Android Task 相关
任务栈?返回栈?启动模式?
面试官装x失败之:Activity的启动模式
taskAffinity的使用
Android Developer-Activity

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

一给

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表