通过dumpsys命令初探ActivityStack、TaskRecord、ActivityRecord的关系

749 阅读5分钟

前言

    Android系统(具体是ActivityManagerService)通过Display、ActivityStack、TaskRecord、ActivityRecord四层来管理页面,那他们分别代表什么意思呢?

  • ActivityRecord 页面记录,这是Android显示的基本单位,具体表现就是每一个ActivityRecord代表我们的一个页面,注意一个页面可能同时在同一或多个任务记录中重复出现多次。
  • TaskRecord 任务记录,也即我们常说的回退栈,记录了单个任务的页面记录列表,具体表现为多任务界面中的一个任务。通常情况下每个应用都是一个任务,除非为某个Activity单独配置了singleInstance或者指定了单独的TaskAffanity。
  • ActivityStack 活动栈,并没有实际的对应物,是Android系统用于管理多任务切换的工具。具体到实际中,在普通模式下每个活动都独占一个栈,Launcher也会单独占用一个栈。在分屏模式下,只有两个活动栈,Launcher以TaskRecord的形式存在于其中一个活动栈中。TaskRecord到达栈底再按返回会切换到同一ActivityStack下的下一个TaskRecord,ActivtyStack到达栈底再按返回会切换到同一Display下的下一个ActivityStack,直至到达Launcher所处的TaskRecord不再响应返回。
  • Display 代表的我们的显示设备,包含Android系统为Display分配的一系列ActivityStack。本文未涉及到多屏的情况。

    任务和应用是两个并不完全重合的概念。应用是功能的合集,而任务则是用户操作流程的体现。任务是自己应用的页面加上从第三方应用借来的页面的总和。(忘了是谁说的了,借用)
    多任务页面是以TaskAffanity来作为任务的身份证的,所以如果多个任务用的都是同一个TaskAffanity那可能只显示最后使用的一个任务。但这不表示未显示的任务死亡了,当你再次使用任务中的页面或者按动返回键触发TaskRecord、ActivtyStack的切换时仍然能重新看到被覆盖的任务。

DEMO应用准备

    本次我们使用了包含三个Activity的DEMO应用,包含一个标准模式启动的主页面、一个SingleTask页面以及一个SingleInstance页面。具体操作是从主页面跳转到SingleInstance页面再跳转到主页面再跳转到SingleTask页面。

dumpsys activity命令

    dumpsys activity命令是系统用来获取ActivityManagerService相关运行数据的工具,直接运行该命令相当于按顺序运行了它的所有18个子命令。下面列出了部分子命令,例如本文讲的activity组件信息可以通过adb shell dumpsys activty activities或者对应的缩写adb shell dumpsys activty a来查看。

命令名称缩写描述
activitiesa查看Activity组件信息
servicess查看Service组件信息
providersprov查看Provider组件信息
broadcastsb查看Broadcast组件信息
intentsi查看Intent信息
processesp查看进程信息

获取运行中的activity相关信息

    输入adb shell dumpsys activty a命令我们即可看到运行中的activity相关信息。输出的数据非常之多,如何得到我们想要的ActivityStack、TaskRecord、ActivityRecord对应关系信息呢?我们在terminal窗口使用快捷键CTRL+F(Mac则是command+F),搜索关键字#即可。因为系统已经贴心的为每一个ActivityStack、TaskRecord、ActivityRecord都分配了一个编号,每多一个段首空格即代表进一步的层级。我们很容易可以总结出下面的这张图:

结构图

  • Display既是对应我们说的Display。
  • Stack既是对应我们说的ActivityStack。
  • Task 既是对应我们说的TaskRecord。
  • Hist 既是对应我们说的ActivityRecord。     可以很详细的看到ActivityStack、TaskRecord、ActivityRecord的关系。每个应用都独占了一个任务栈。使用SingleInstance启动的活动单独占用了一个任务记录和任务栈。为什么我们打开多任务页面却看不到SingleInstanceActivity对应的任务记录?这是因为在不做任何配置的情况下两个任务栈使用的TaskAffanity都是MainActivity的包名,多任务页面只显示了最后使用的这个任务记录。当你点击两次返回时,即可看到SingleInstanceActivity页面,同时多任务页面也显示为这个任务记录。

分屏时的activity信息

    我们分屏并再打开一个Chrome应用,再次调用命令查看Activity信息。注意搜索框必须重新输入#号否则不会触发搜索。

结构图

    Stack#3和Stack#4即是系统为分屏创建的两个ActivtyStack,可以看到此时Launcher不再独占一个活动栈而是作为其中一个活动栈下的任务记录而存在,同时新打开的任务记录也不再创建新的活动栈而是依附于分屏的活动栈。激活Stack#4所在的分屏页面后按返回会跳转到Launcher页面,而激活Stack#3所在的分屏页面后按返回会结束分屏。

总结

    通过dumpsys activity activities命令我们简单的探索了一下ActivityStack、TaskRecord、ActivityRecord的关系,对此有了一个初步的印象,这对于我们进一步阅读源码有一定的帮助。如果文章中存在任何的错误,欢迎在评论区指出,感谢!