四大组件之ActivityRecord

本文详细解析了Android系统中ActivityRecord的结构与作用,包括其在Activity生命周期管理中的关键角色,如启动、暂停、停止等状态变化,以及与TaskRecord、ActivityStack等组件的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一. 引言

BroadcastRecord,ServiceRecord都继承于Binder对象,而ActivityRecord并没有继承于Binder。 但ActivityRecord的成员变量appToken的数据类型为Token,Token继承于IApplicationToken.Stub。

appToken:system_server进程通过调用scheduleLaunchActivity()将appToken传递到App进程,

  • 调用createActivityContext(),保存到ContextImpl.mActivityToken
  • 调用activity.attach(),保存到Activity.mToken;

ServiceRecord本身继承于Binder对象,传递到客户端的代理:

  • 调用Service.attach(),保存到Service.mToken;
  • 用途:stopSelf,startForeground, stopForeground

二. ActivityRecord结构体

先以一幅图来展示AMS管理Activity所涉及的相关数据结构: 点击查看大图

  • ActivityRecord: 记录着Activity信息
  • TaskRecord: 记录着task信息
  • ActivityStack: 栈信息

2.1 ActivityRecord

Activity的信息记录在ActivityRecord对象, 并通过通过成员变量task指向TaskRecord

  • ProcessRecord app //跑在哪个进程
  • TaskRecord task //跑在哪个task
  • ActivityInfo info // Activity信息
  • int mActivityType //Activity类型
  • ActivityState state //Activity状态
  • ApplicationInfo appInfo //跑在哪个app
  • ComponentName realActivity //组件名
  • String packageName //包名
  • String processName //进程名
  • int launchMode //启动模式
  • int userId // 该Activity运行在哪个用户id

再来说一说Activity类型和Activity状态的常量:

mActivityType:

  • APPLICATION_ACTIVITY_TYPE:普通应用类型
  • HOME_ACTIVITY_TYPE:桌面类型
  • RECENTS_ACTIVITY_TYPE:最近任务类型

ActivityState:

  • INITIALIZING
  • RESUMED:已恢复
  • PAUSING
  • PAUSED:已暂停
  • STOPPING
  • STOPPED:已停止
  • FINISHING
  • DESTROYING
  • DESTROYED:已销毁

最后,说一说时间相关的成员变量:

时间点赋值时间含义
createTimenew ActivityRecordActivity首次创建时间点
displayStartTimeAS.setLaunchTimeActivity首次启动时间点
fullyDrawnStartTimeAS.setLaunchTimeActivity首次启动时间点
startTimeActivity上次启动的时间点
lastVisibleTimeAR.windowsVisibleLockedActivity上次成为可见的时间点
cpuTimeAtResumeAS.completeResumeLocked从Rsume以来的cpu使用时长
pauseTimeAS.startPausingLockedActivity上次暂停的时间点
launchTickTimeAR.startLaunchTickingLockedEng版本才赋值
lastLaunchTimeASS.realStartActivityLocked上一次启动时间

其中AR是指ActivityRecord, AS是指ActivityStack。

2.2 TaskRecord

Task的信息记录在TaskRecord对象.

  • ActivityStack stack; //当前所属的stack
  • ArrayList mActivities; // 当前task的所有Activity列表
  • int taskId
  • String affinity; 是指root activity的affinity,即该Task中第一个Activity;
  • int mCallingUid;
  • String mCallingPackage; //调用者的包名

2.3 ActivityStack

  • ArrayList mTaskHistory //保存所有的Task列表
  • ArrayList mStacks; //所有stack列表
  • final int mStackId;
  • int mDisplayId;
  • ActivityRecord mPausingActivity //正在pause
  • ActivityRecord mLastPausedActivity
  • ActivityRecord mResumedActivity //已经resumed
  • ActivityRecord mLastStartedActivity

所有前台stack的mResumedActivity的state == RESUMED, 则表示allResumedActivitiesComplete, 此时mLastFocusedStack = mFocusedStack;

2.4 ActivityStackSupervisor

  • ActivityStack mHomeStack //桌面的stack
  • ActivityStack mFocusedStack //当前聚焦stack
  • ActivityStack mLastFocusedStack //正在切换
  • SparseArray mActivityDisplays //displayId为key
  • SparseArray mActivityContainers // mStackId为key

home的栈ID等于0,即HOME_STACK_ID = 0;

三. Activity栈关系

3.1 Stack组成图

Activity栈结构体的组成关系,点击查看大图

  • 一般地,对于没有分屏功能以及虚拟屏的情况下,ActivityStackSupervisor与ActivityDisplay都是系统唯一;
  • ActivityDisplay主要有Home Stack和App Stack这两个栈;
  • 每个ActivityStack中可以有若干个TaskRecord对象;
  • 每个TaskRecord包含如果个ActivityRecord对象;
  • 每个ActivityRecord记录一个Activity信息。

(1)正向关系链表:

ActivityStackSupervisor.mActivityDisplays 
-> ActivityDisplay.mStacks 
-> ActivityStack.mTaskHistory 
-> TaskRecord.mActivities 
-> ActivityRecord

(2)反向关系链表:

ActivityRecord.task 
-> TaskRecord.stack 
-> ActivityStack.mStackSupervisor
-> ActivityStackSupervisor

注:ActivityStack.mDisplayId可找到所对应的ActivityDisplay;

四. 启动过程

Activity启动与停止流程,点击查看大图

Activity的pause情况:

  • 当Activity A启动到Activity B,则需要pause掉Activity A;
  • 当系统需要进入休眠状态或许shutdown的过程;
  • 当activity需要finish的过程。

Activity的stop情况:

  • 当Activity处于不可见状态,则需要stop该Activity;
  • 为了更好的用户体验,先resume新的Activity,再待进入idle状态(即没有用户操作)再去stop旧的Activity;

更多源码详细过程,见startActivity启动过程分析

以上内容转自gityuan的博客:四大组件之ActivityRecord - Gityuan博客 | 袁辉辉的技术博客http://gityuan.com/2017/06/11/activity_record/四大组件之ActivityRecord - Gityuan博客 | 袁辉辉的技术博客

------------------------------------------------------------------------分割线------------------------------------------------------------------------------------

以下内容为个人总结:

参考:Android 7.0中的多窗口-分屏-实现解析_淡淡的宁静的博客-优快云博客

           Android实现双屏异显_淡淡的宁静的博客-优快云博客

          https://developer.android.google.cn/guide/topics/ui/multi-window

关于gityuan所说的这个结论“对于没有分屏功能以及虚拟屏的情况下,ActivityStackSupervisor与ActivityDisplay都是系统唯一

 我的观点是,无论有多少个Display(一个物理屏幕对应一个Display对象,由DisplayManagerService管理)都只有一个ActivityStackSupervisor,而Android N的分屏功能启用后,也只有一个ActivityStackSupervisor$ActivityDisplay实例,实际对应的是DisplayManager#getDisplay(DisplayManager.DEFAULT_DISPLAY);

只有一个物理屏幕,且在没有分屏的情况下,有两个ActivityStack,一个是包含了Launcher所在的Stack,这个Stack实际也包含了RecentsActivity,即触摸虚拟按键overview弹出的那个,这个stack即是ActivityStackSupervisor#mHomeStack,对应的stackId为ActivityManager#HOME_STACK_ID。而其他一般的Activity则存在于stackId为ActivityManager#FULLSCREEN_WORKSPACE_STACK_ID的ActivityStack。如果启动分屏模式的话,则出现上半屏幕的Activity所在的Task则会被移到stackId为ActivityManager#DOCKED_STACK_ID的ActivityStack,如果没有的话则创建一个。然后选择一个Activity显示在下半屏,那么这个Activity所在的Task是属于ActivityManager#FULLSCREEN_WORKSPACE_STACK_ID,虽然不是全屏显示。

上下两个Activity只有一个是处于resumed状态的,另一个是处于paused状态的,虽然是可见。这个就区分开了那个Activity是获得焦点的,即获得按键事件和其他只有获得焦点的Activity才能接收的事件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值