AMS重要的数据结构

基于Android U

ActivityRecord

ActivityRecord内部记录了Activity的所有信息。因此它用来描述一个Activity,它是在启动Activity时被创建的,具体是在ActivityStarter的startActivity方法中被创建的。ActivityRecord的部分重要成员变量如下所示:

名称 类型 说明
service ActivityManagerService AMS的引用
info ActivityInfo 开发者在AndroidManifest中提供的Activity信息
launchedFromPackage String 启动Activity的包名
taskAffinity String Activity希望归属的栈
task Task ActivityRecord所在的Task
app WindowProcessController ActivityRecord所在的应用程序进程
mState State 当前Activity的状态
icon int Activity的图标资源标识符
theme int Activity的主题资源标识符

ActivityRecord中含有该ActivityRecord所在的Task,这就将ActivityRecord和Task关联在一起,它们是Activity任务栈模型的重要成员。

TaskFragment

一个基本容器,可容纳 Activity 或其他 TaskFragment,还能够管理Activity生命周期及更新其可见性。

在TaskFragment中定义了一些特殊状态的Activity,如下所示:

1
2
3
4
frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java
private ActivityRecord mPausingActivity = null; // 正在暂停的Activity
ActivityRecord mLastPausedActivity = null; // 上一个已经暂停的Activity
private ActivityRecord mResumedActivity = null; // 已经Resume的Activity

Task

Task是一个TaskFragment(继承自TaskFragment),用来描述一个Activity任务栈,其内部也有很多的成员变量,如下所示:

名称 类型 说明
mTaskId int 任务栈的唯一标识符
affinity String 任务栈的倾向性
intent Intent 启动这个任务栈的Intent,可能为null

Task内部存储了任务栈的所有信息,包括任务栈的唯一标识符、任务栈的倾向性、任务栈中的Activity记录等。

ActivityState

在ActivityRecord中通过枚举存储了Activity的所有的状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
enum State {
INITIALIZING,
STARTED,
RESUMED,
PAUSING,
PAUSED,
STOPPING,
STOPPED,
FINISHING,
DESTROYING,
DESTROYED,
RESTARTING_PROCESS
}

ActivityTaskSupervisor

用来替代ActivityStackSupervisor,是Activity的核心调度类,其中有一些Activity List。

1
2
3
4
5
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
private final ArrayList<WaitInfo> mWaitingActivityLaunched = new ArrayList<>(); // 等待launch还不可见的Activity
final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<>(); // 正在stop的Activity
final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<>(); // 正在finish的Activity
final ArrayList<ActivityRecord> mNoHistoryActivities = new ArrayList<>(); // 没有历史记录的Activity

Activity栈管理

有了栈管理,我们可以对应用程序进行操作,应用可以复用自身应用中以及其他应用的Activity,节省了资源。比如我们使用一款社交应用,这个应用的联系人详情界面提供了联系人的邮箱,当我们点击邮箱时会跳到发送邮件的界面。

Launch Mode

用于设定Activity的启动方式,无论是哪种启动方式,所启动的Activity都会位于Activity栈的栈顶,主要有以下四种Launch Mode:

  • standard:默认模式,每次启动Activity都会创建一个新的Activity实例。

  • singleTop:如果要启动的Activity已经在栈顶,则不会重新创建Activity,同时该Activity的onNewIntent()方法会被调用。如果要启动的Activity不在栈顶,则会重新创建该Activity的实例。

  • singleTask:如果要启动的Activity已经存在于它想要归属的栈中,那么将栈中位于该Activity上的所有Activity出栈,同时该Activity的onNewIntent()方法会被调用。如果要启动的Activity不存在于它想要归属的栈中,如果该栈存在,则创建该Activity的实例,如果该栈不存在,则首先要创建一个新栈,然后创建该Activity实例并压入到新栈中。

  • singleInstance:启动Activity时,首先要创建一个新栈,然后创建该Activity实例并压入新栈中,新栈中只会存在这一个Activity实例。

Intent的FLAG

在Intent中定义了很多FLAG,其中有几个FLAG也可以设定Activity的启动方式,如果Launch Mode和FLAG设定的Activity的启动方式有冲突,则以FLAG设定的为准。

  • FLAG_ACTIVITY_SINGLE_TOP:和Launch Mode中的singleTop效果一样。
  • FLAG_ACTIVITY_NEW_TASK:和Launch Mode中的singleTask效果一样。
  • FLAG_ACTIVITY_CLEAR_TOP:Launch Mode中没有与此对应的模式,如果要启动的Activity已经存在于栈中,则将所有位于它上面的Activity出栈。singleTask默认具有此标记的效果。

除了上述三个FLAG,还有一个FLAG和栈管理相关。

  • FLAG_ACTIVITY_NO_HISTORY:Activity一旦退出,就不会存在于栈中。同样地,也可以在AndroidManifest.xml中设置android:noHistory。
  • FLAG_ACTIVITY_MULTIPLE_TASK:需要和FLAG_ACTIVITY_NEW_TASK一同使用才有效果,系统会启动一个新的栈来容纳新启动的Activity。
  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:Activity不会被放入到“最近启动的Activity”列表中。
  • FLAG_ACTIVITY_BROUGHT_TO_FRONT:这个标志位通常不是由应用程序中的代码设置的,而是Launch Mode为singleTask时,由系统加上的。
  • FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY:这个标志位通常不是由应用程序中的代码设置的,而是从历史记录中启动的(长按Home键调出)。
  • FLAG_ACTIVITY_CLEAR_TASK:需要和FLAG_ACTIVITY_NEW_TASK一同使用才有效果,用于清除与启动的Activity相关栈的所有其他Activity。
taskAffinity

我们可以在AndroidManifest.xml中设置android:taskAffinity,用来指定Activity希望归属的栈,在默认情况下,同一个应用程序的所有的Activity都有着相同的taskAffinity。taskAffinity在下面两种情况时会产生效果。

(1)taskAffinity与FLAG_ACTIVITY_NEW_TASK或者singleTask配合。如果新启动Activity的taskAffinity和栈的taskAffinity相同则加入到该栈中;如果不同,就会创建新栈。

(2)taskAffinity与allowTaskReparenting配合。如果allowTaskReparenting为true,说明Activity具有转移的能力。举例:当社交应用启动了发送邮件的Activity,此时发送邮件的Activity是和社交应用处于同一个栈中的,并且这个栈位于前台。如果发送邮件的Activity的allowTaskReparenting设置为true,此后E-mail应用所在的栈位于前台时,发送邮件的Activity就会由社交应用的栈转移到与它更亲近的邮件应用(taskAffinity相同)所在的栈中。


AMS重要的数据结构
https://citrus-maxima.github.io/2024/03/10/AMS重要的数据结构/
作者
柚子树
发布于
2024年3月10日
许可协议