AMS中最重要的数据结构-TaskRecord(任务栈)

前面两篇文章Activity启动模式与TaskAffinity属性和Intent与启动模式相关的Flag简介 ,想必大家对任务栈有了一定理解。

1.什么是任务(栈)

1.在 Android 中,每一件事可以被看作是一个 Task,一个 Task 又可以被细分成多个子步骤,每个子步骤可以被看作是一个 Activity。任务是用户在执行某项工作时与之互动的一系列 Activity 的集合。这些 Activity 按照每个 Activity 打开的顺序排列在一个返回堆栈中。堆栈中的 Activity 永远不会重新排列,只会被送入和退出,在当前 Activity 启动时被送入堆栈,在用户使用返回按钮离开时从堆栈中退出。因此,返回堆栈按照“后进先出”的对象结构运作,所以也叫任务栈

小结:

  • 每一个应用进程就是一个任务,这个任务中又包含多个Activity,如果不指明,那么一个应用会共享自己同一个任务栈,当然应用自己可以定义多个任务。
  • 整个Activity的堆栈是由多个任务堆叠而成的,每个任务里面又可以管理自己的返回栈,任务里面的Activity是有顺序的。
  • 任务列表是有顺序排列的,同一个任务中的activity增减是activity的入退场,而当这个任务中的activity都被出栈完后就涉及到切任务和activity退场两个逻辑。
  • 因为堆栈中的Activity永远不会重新排列,所以如果要起的Activity是一个singleTask的,那么在这个Task中这个Activity之上还有其他Activity的都会被finish掉,以便能够让它被显示到前台。

直观感受:

比如当用户使用浏览器时,按共享 > Gmail。系统会显示 Gmail 应用的写邮件屏幕。此时点按“最近”按钮会显示 Chrome 和 Gmail 作为单独的任务运行。(此时启动Gmail邮件Activity加了FLAG_ACTIVITY_NEW_TASK才会在最近任务列表中出现两个任务(栈),若不加这个FALG,以标准模式启动Gmail Activty,此时在最近任务屏幕只会有一个任务(栈),栈顶是邮件Activity,栈底是浏览器Activty)

2、什么是返回栈

返回栈是从用户使用的角度来进行定义的,返回栈中包含一个或多个任务栈返回栈所表示的就是当用户不断回退页面时所能看到的一系列 Activity 的集合,这些页面可能是处于多个不同的任务栈中。但同时只会有一个任务栈够处于前台,只有处于前台任务栈的 Activity 才能与用户交互。

2.1 示例1

例如,用户先启动了应用 A,先后打开了 Activity 1 和 Activity 2,此时 Task A 是前台任务栈。之后用户又点击 Home 键回到了桌面,启动了应用 B,又先后打开了 的 Activity 3 和 Activity 4,此时 Task B 就成为了前台任务栈,Task A 成了后台任务栈。用户点击返回键的过程中依次展现的页面就会是 Activity 4 -> Activity 3 -> 桌面

而如果用户在打开应用 B 时并没有回到桌面,而是直接通过应用 A 启动了应用 B 的话,用户点击返回键的过程中依次展现的页面就会是 Activity 4 -> Activity 3 -> Activity 2 -> Activity 1 -> 桌面

而第一种情况中,返回栈只包含 Task B 一个任务栈,所以当 Task B 被清空后就会直接回到桌面。在第二种情况中,返回栈中包含 Task A 和 Task B 两个任务栈,所以当 Task B 被清空后也会先切回到 Task A,等到 Task A 也被清空后才会回到桌面

2.2 示例2

假设有三个应用,每个应用都有3个Activity,按首页,二级页,三级页面,分别为A,B,C。其中所有应用的根Activity-首页A都是singleTask,每个应用的C-Activity会启动下一个应用的首页A-Activity。最终这三个应用会分别起三个任务Task,每个任务中有三个Activity,此时它们的顺序如下:

app1_A->app1_B->app1_c->
app2_A->app2_B->app2_c->
app3_A->app3_B->app3_c
他们的task列表为:app1->app2->app3,如果不停的按下返回键,它们会按倒序进行退出。

我们把app2_B是设成singleTask的Activity(如下图上半部分标红位置 ,我们在app3_c中启动app2_B,这时就会强制把app2这个任务切到前台,并展示app2_B,因为在app2中,app2_C在app2_B的上面,所以app2_C会退栈销毁,这时app2_B就会显示在前台了。又因为app2被切换到前台,所以现在的task列表变成:
app1->app3->app2 所以在返回栈中activity的从底到顶顺序为:
app1_A->app1_B->app1_c->app3_A->app3_B->app3_c->app2_A->app2_B
当你按返回键时,会依次从后到前看到这些Activity。

3.任务栈的数据结构

Task 用数据结构 TaskRecord 表示。Task 中有一个 ActivityRecord 的集合 mActivities,它是以 Stack 的方式来管理其中的 Activity。先上一张数据结构的概览图:

总体架构:

图中的方框可以理解为一个中包含关系:譬如一个TaskRecord中包含多个ActivityRecord; 图中的连接线可以理解为等价关系,譬如同一个ActivityRecord会被TaskRecord和ProcessRecord引用,两者是从不同维度来管理ActivityRecord。

  • ActivityRecord是Activity管理的最小单位,它对应着一个用户界面;
  • TaskRecord也是一个栈式管理结构,每一个TaskRecord都可能存在一个或多个ActivityRecord,栈顶的ActivityRecord表示当前任务可见的界面;
  • ActivityStack是一个栈式管理结构,每一个ActivityStack都可能存在一个或多个TaskRecord,栈顶的TaskRecord表示当前可见的任务;
  • ActivityStackSupervisor管理着多个ActivityStack,但当前只会有一个获取焦点(Focused)的ActivityStack;
  • ProcessRecord记录着属于一个进程的所有ActivityRecord,运行在不同TaskRecord中的ActivityRecord可能是属于同一个 ProcessRecord。
  • 同一个TaskRecord的ActivityRecord可能分别处于不同的进程中,每个ActivityRecord所处的进程跟task没有关系

 前台任务栈和后台任务栈:当有多个 Task 时,Android 系统只支持一个处于前台的 Task,其余的 Task 均处于后台,这些后台 Task 内部 Activity 保持顺序不变,用户可以一次将整 个Task 挪到后台或置为前台。

4.查看任务栈信息

查看任务栈命令:adb shell dumpsys activity activities

Task id #30
  TaskRecord{7f2f34a #30 A=com.maweiqi.second U=0 sz=2}
    Intent { flg=0x10000000 cmp=com.open.android.task1/.SecondActivity }
     Hist #1: ActivityRecord{a0f9ded u0 com.open.android.task3/.OtherActivity t30}
       Intent { flg=0x10400000 cmp=com.open.android.task3/.OtherActivity }
       ProcessRecord{12090b5 27543:com.open.android.task3/u0a62}
      Hist #0: ActivityRecord{1048af6 u0 com.open.android.task1/.SecondActivity t30}
       Intent { flg=0x10000000 cmp=com.open.android.task1/.SecondActivity }
       ProcessRecord{5bc013e 26035:com.open.android.task1/u0a59}

 Task id #31
   TaskRecord{dce52bb #31 A=com.open.android.task3 U=0 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.open.android.task3/.MainActivity }
        Hist #0: ActivityRecord{f9e58c5 u0 com.open.android.task3/.MainActivity t31}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.open.android.task3/.MainActivity }
          ProcessRecord{12090b5 27543:com.open.android.task3/u0a62}

 Task id #29
      TaskRecord{5b063d8 #29 A=com.open.android.task1 U=0 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.open.android.task1/.MainActivity }
        Hist #0: ActivityRecord{689947d u0 com.open.android.task1/.MainActivity t29}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.open.android.task1/.MainActivity }
          ProcessRecord{5bc013e 26035:com.open.android.task1/u0a59}

Running activities (most recent first):
   TaskRecord{7f2f34a #30 A=com.maweiqi.second U=0 sz=2}
        Run #3: ActivityRecord{a0f9ded u0 com.open.android.task3/.OtherActivity t30}
   TaskRecord{dce52bb #31 A=com.open.android.task3 U=0 sz=1}
        Run #2: ActivityRecord{f9e58c5 u0 com.open.android.task3/.MainActivity t31}
   TaskRecord{7f2f34a #30 A=com.maweiqi.second U=0 sz=2}
       Run #1: ActivityRecord{1048af6 u0 com.open.android.task1/.SecondActivity t30}
   TaskRecord{5b063d8 #29 A=com.open.android.task1 U=0 sz=1}
       Run #0: ActivityRecord{689947d u0 com.open.android.task1/.MainActivity t29}

mResumedActivity: ActivityRecord{a0f9ded u0 com.open.android.task3/.OtherActivity t30}

这些信息能够很好的反馈上面任务栈的数据结构。

5.TaskRecord属性

TaskRecord的职责是管理多个ActivityRecord,本文所述的任务、任务栈指的就是TaskRecord。 启动Activity时,需要找到Activity的宿主任务,如果不存在,则需要新建一个,也就是说所有的ActivityRecord都必须有宿主。 TaskRecord与ActivityRecord是一对多的关系,TaskRecord的属性中包含了ActivityRecord的数组; 同时,TaskRecord还需要维护任务栈本身的状态。

属性描述
taskidTaskRecord的唯一标识
taskType任务栈的类型,等同于ActivityRecord的类型,是由任务栈的第一个ActivityRecord决定的
intent在当前任务栈中启动的第一个Activity的Intent将会被记录下来,后续如果有相同的Intent时,会与已有任务栈的Intent进行匹配,如果匹配上了,就不需要再新建一个TaskRecord了
realActivity, origActivity启动任务栈的Activity,这两个属性是用包名(CompentName)表示的,real和orig是为了区分Activity有无别名(alias)的情况,如果AndroidManifest.xml中定义的Activity是一个alias,则此处real表示Activity的别名,orig表示真实的Activity
affinityTaskRecord把Activity的affinity记录下来,后续启动Activity时,会从已有的任务栈中匹配affinity,如果匹配上了,则不需要新建TaskRecord
rootAffinity记录任务栈中最底部Activity的affinity,一经设定后就不再改变
mActivities这是TaskRecord最重要的一个属性,TaskRecord是一个栈结构,栈的元素是ActivityRecord,其内部实现是一个数组mActivities
stack当前TaskRecord所在的ActivityStack


6.后记

 后面文章将深入部分函数的代码来了解TaskRecord的工作原理及AMS其他数据结构。

  • 18
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: ams-server-2022-07-21.rar 是一个文件的名称。这个文件是一个压缩包,文件格式为.rar。根据文件名可以推测,这个文件是关于"ams-server"的,日期为2022年7月21日。 "ams-server"代表了一个可能是"Attendance Management System Server"(考勤管理系统服务器)的缩写。这个服务器可能是一个用于管理和处理考勤系统数据的应用程序。 通过这个压缩包,我们可以猜测其包含了与该考勤管理系统服务器相关的文件和数据。可能会有服务器的配置文件、源代码、数据库备份文件或其他相关的文档和资料。 如果需要使用这个压缩包,首先需要将其解压缩。通常情况下,我们可以使用压缩软件(比如WinRAR、7-Zip等)来解压缩RAR文件。在解压缩之后,我们可以查看其的内容,并按照需求进行相应的操作。 总而言之, "ams-server-2022-07-21.rar"是一个压缩文件,可能包含了与考勤管理系统服务器相关的文件和数据。不同的应用场景可能需要不同的操作和处理。 ### 回答2: ams-server-2022-07-21.rar是一个文件的名称。根据名称可以猜测它是一个压缩文件,并且可能与ams服务器的某个版本或日期相关。根据“-2022-07-21”的部分,可以猜测这个压缩文件可能是为2022年7月21日的ams服务器版本制作的。 根据常见的命名规则,"ams-server"可能是指ams服务器的名称或缩写。服务器是一种计算机程序,用于提供服务、管理资源和处理请求。ams可能是一个特定的项目、软件或系统。压缩文件通常用于将多个文件或文件夹压缩成一个单独的文件,以便在网络上传输或存储时占用更少的空间。 因此,ams-server-2022-07-21.rar可能是一个存档了该日期的ams服务器相关文件的压缩文件。使用解压缩软件可以将压缩文件解压缩,以获得存档内的所有文件和文件夹。解压后的文件可能包含ams服务器的程序、配置文件、日志文件或其他与服务器操作相关的文件。 需要注意的是,这只是对文件名称的推测,实际内容可能有所不同。要确切了解ams-server-2022-07-21.rar文件的内容和用途,需要进一步查看文件、文档或与文件相关的信息。 ### 回答3: ams-server-2022-07-21.rar 是一个压缩文件,扩展名为.rar。根据名称可以推测,这个文件可能是一个AMS服务器的软件包,版本为2022年7月21日。rar 是一种流行的压缩格式,通常用于将多个文件或文件夹打包成一个单独的文件。通过解压缩该文件,我们可以获得其的内容。 解压缩过程首先需要一个解压软件,如WinRAR或7-Zip等。我们可以将ams-server-2022-07-21.rar 文件拖放到解压软件的窗口,或者使用软件的解压缩功能。解压缩后会生成一个或多个文件和文件夹,这些文件和文件夹可能包含了AMS服务器的程序文件、配置文件、文档等。 根据文件名的日期,可以判断这个软件包是在2022年7月21日创建的。这可能表示该版本的AMS服务器在该日期之前是最新的,提供了一些新功能、修复或改进。用户可以下载和安装这个软件包,以使用其提供的更新功能,或者修复现有版本的问题。 总之,ams-server-2022-07-21.rar 是一个AMS服务器的压缩软件包,文件名反映了其创建日期。通过解压缩该文件,我们可以访问其的内容,并使用其的文件来更新或改进现有的AMS服务器。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值