【Android 13源码分析】Activity生命周期之onCreate,onStart,onResume-1
忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。
– 服装学院的IT男
本篇已收录于Activity短暂的一生系列
欢迎一起学习讨论Android应用开发或者WMS
V:WJB6995
Q:707409815
正文
生命周期系列:
-
Activity生命周期之onPause
-
onCreate,onStart,onResume-1
-
onCreate,onStart,onResume-2
-
Activity生命周期之onStop-1
-
Activity生命周期之onStop-2
-
Activity生命周期之onDestory
在整个启动流程中,上一篇介绍了第一阶段:SourceActivity 的 onPause
现在分析第二阶段:TargetActivity 启动后会依次执行 onCreate,onStart,onResume。
另外还会完整的介绍一下 Activity 生命周期的事务是如何触发的。
1. 启动流程介绍
我们知道 onCreate 这个生命周期表示 Activity 的创建,对应 LaunchActivityItem 这个事务,源码中构建这个事务唯一的地方就在 ActivityTaskSupervisor::realStartActivityLocked 方法。
而 ActivityTaskSupervisor::realStartActivityLocked 方法的执行逻辑,在[Activity启动流程系列]说过要启动 TargetActivity 有2个必要条件:
-
- TargetActivity 所在的应用进程已经启动
-
- SourceActivity 需要执行 onPause
不考虑异常情况,能执行 onCreate 的场景就是冷热启动了,冷热启动区别也就在于多了个需要创建应用进程,不过最终都会执行到 ActivityTaskSupervisor::realStartActivityLocked 方法。
无论是启动进程后执行过来的,还是上篇提到的 SourceActivity 执行 activityPaused 流程触发过来的结果都是一样的,不必太在意
开始撸代码
# ActivityTaskSupervisor boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,boolean andResume, boolean checkConfig) throws RemoteException {// 1. 判断是否执行完了pause 。 也就是2个条件之一,必须要执行完pause才可以进入后面if (!mRootWindowContainer.allPausedActivitiesComplete()) {// While there are activities pausing we skipping starting any new activities until// pauses are complete. NOTE: that we also do this for activities that are starting in// the paused state because they will first be resumed then paused on the client side.// 不满足添加就打logProtoLog.v(WM_DEBUG_STATES,"realStartActivityLocked: Skipping start of r=%s some activities pausing...",r);return false;}......// 2. wm_restart_activity EventLogTags.writeWmRestartActivity(r.mUserId, System.identityHashCode(r),task.mTaskId, r.shortComponentName);// 3.重点* 创建Activity启动事务.将构建的 LaunchActivityItem 添加到 clientTransaction 中final ClientTransaction clientTransaction = ClientTransaction.obtain(proc.getThread(), r.token);......clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),System.identityHashCode(r), r.info,// TODO: Have this take the merged configuration instead of separate global// and override configs.mergedConfiguration.getGlobalConfiguration(),mergedConfiguration.getOverrideConfiguration(), r.compat,r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),results, newIntents, r.takeOptions(), isTransitionForward,proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken));final ActivityLifecycleItem lifecycleItem;if (andResume) {// 4.重点*. 设置预期的最终状态Resume逻辑,启动走的这。 表示需要执行到onCreatelifecycleItem = ResumeActivityItem.obtain(isTransitionForward);} else {// Pause 逻辑lifecycleItem = PauseActivityItem.obtain();}clientTransaction.setLifecycleStateRequest(lifecycleItem);// 5.重点* 调度事务,将clientTransaction添加到生命周期管理器中mService.getLifecycleManager().scheduleTransaction(clientTransaction);}
-
- 如果有Activity没有执行完 pause ,则不能执行新的Activity的启动。 如果不满足条件也会相应的ProtoLog
-
- 打印Events日志,格式为:wm_restart_activity: [0,253598020,21,com.google.android.dialer/.extensions.GoogleDialtactsActivity]
-
- 构建 LaunchActivityItem 事务,将会触发创建Activity,并执行到 onCreate
-
- 构建 ResumeActivityItem 事务,将会触发执行到Activity的 onResume
-
- 执行事务
后面的流程其实可以直接去看应用端这2个事务的执行,不过我对这中间的调用比较好奇,所以把生命周期跨进程调用事务的逻辑也梳理了一遍。对这块比较了解的可以跳过,直接看第三章生命周期相关的内容
2. Activity 生命周期事务跨进程处理方式详解
2.1 了解ClientTransaction
在 ActivityTaskSupervisor::realStartActivityLocked 方法中对跨进程执行生命周期事务的代码可以归纳为以下几步:
-
- 构建出 ClientTransaction
-
- 构建 onCreate 和 onResume对应的2个事务,并保存到 ClientTransaction 中
-
- 通过 ClientLifecycleManager::scheduleTransaction 方法来触发事务的调度执行,唯一参数就是 ClientTransaction
这一小节先来了解一下这个 ClientTransaction 到底是什么
# ClientTransaction// 实现Parcelable接口,说明可序列化public class ClientTransaction implements Parcelable, ObjectPoolItem {// 几个重要的成员变量private List<ClientTransactionItem> mActivityCallbacks;private ActivityLifecycleItem mLifecycleStateRequest;// 目标进程private IApplicationThread mClient;// 目标Activityprivate IBinder mActivityToken;// client :对应进程// activityToken :创建ActivityRecord时的匿名tokenpublic static ClientTransaction obtain(IApplicationThread client, IBinder activityToken) {ClientTransaction instance = ObjectPool.obtain(ClientTransaction.class);if (instance == null) {instance = new ClientTransaction();}instance.mClient = client;instance.mActivityToken = activityToken;return instance;}// 拿到对应public IBinder getActivityToken() {return mActivityToken;}public void addCallback(ClientTransactionItem activityCallback) {if (mActivityCallbacks == null) {mActivityCallbacks = new ArrayList<>();}// 事务添加到 mActivityCallbacks 列表中mActivityCallbacks.add(activityCallback);}// 事务赋值给 mLifecycleStateRequest 变量public void setLifecycleStateRequest(ActivityLifecycleItem stateRequest) {mLifecycleStateRequest = stateRequest;}// 目标进程执行事务public void schedule() throws RemoteException {mClient.scheduleTransaction(this);}}
ClientTransaction 的核心方法就这些,结合 ActivityTaskSupervisor::realStartActivityLocked 方法的使用得出以下结论:
-
- ClientTransaction::obtain 构建出一个 ClientTransaction 对象,2个参数分别为目标进程,和目标Activity
-
- addCallback 方法会将 LaunchActivityItem 放到 内部的 mActivityCallbacks 列表中
-
- setLifecycleStateRequest 方法将 ResumeActivityItem 事务赋值给了 mLifecycleStateRequest 变量。
这里还有个重要的方法 schedule() ,最终会触发目标进程执行当前这个 ClientTransaction 。
2.2 事务的调度执行
上一小节知道生命周期的事务都被包装在了一个 ClientTransaction 对象中,现在来看看 ClientLifecycleManager::scheduleTransaction 方法是如何触发对应事务执行的。
该方法有多个重载,但是本质都一样
# ClientLifecycleManagervoid scheduleTransaction(ClientTransaction transaction) throws RemoteException {final IApplicationThread client = transaction.getClient();// 重点* 调用ClientTransaction::scheduletransaction.schedule();......}void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,@NonNull ActivityLifecycleItem stateRequest) throws RemoteException {// 构建 一个 ClientTransaction,调用上面的scheduleTransactionfinal ClientTransaction clientTransaction = transactionWithState(client, activityToken,stateRequest);scheduleTransaction(clientTransaction);}......忽略另外几个重载, 都是内部构建出一个 ClientTransaction
主要就是执行了 ClientTransaction::schedule 方法。
2.3 应用进程处理
ClientTransaction::schedule 方法会跨进程调用到目标进程的 scheduleTransaction 方法,我们知道进程指的就是 ActivityThread 内部类 ApplicationThread
# ActivityThread$ApplicationThread@Overridepublic void scheduleTransaction(ClientTransaction transaction) throws RemoteException {// 这里调用的是ActivityThread的父类 ClientTransactionHandlerActivityThread.this.scheduleTransaction(transaction);}# ClientTransactionHandlervoid scheduleTransaction(ClientTransaction transaction) {// 执行 preExecute (预执行)transaction.preExecute(this);// 重点* 发送消息sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);}
先执行 preExecute 方法,最重要的是执行发送了一个 EXECUTE_TRANSACTION 消息,并把 ClientTransaction 传过去了。
这个消息的处理在 ActivityThread 中。
# ActivityThreadprivate final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);class H extends Handler {public void handleMessage(Message msg) {if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));switch (msg.what) {......case EXECUTE_TRANSACTION:final ClientTransaction transaction = (ClientTransaction) msg.obj;// 处理mTransactionExecutor.execute(transaction);......break;......}}}
ClientTransaction 又被传递到 TransactionExecutor 中处理了。
# TransactionExecutorpublic void execute(ClientTransaction transaction) {......// LaunchActivityItemexecuteCallbacks(transaction);// ResumeActivityItemexecuteLifecycleState(transaction);......}
2.3.1 executeCallbacks 和 executeLifecycleState 方法
为什么我在上面注释里说 executeCallbacks 是处理 LaunchActivityItem,executeLifecycleState 是处理 ResumeActivityItem 呢?
代码中有答案:
# TransactionExecutorpublic void executeCallbacks(ClientTransaction transaction) {// 获取 callback 的元素,没有就返回final List<ClientTransactionItem> callbacks = transaction.getCallbacks();if (callbacks == null || callbacks.isEmpty()) {// No callbacks to execute, return early.return;}......// 当前场景是触发 LaunchActivityItem的execute方法item.execute(mTransactionHandler, token, mPendingActions);item.postExecute(mTransactionHandler, token, mPendingActions);......}private void executeLifecycleState(ClientTransaction transaction) {// 获取tLifecycleStateRequest,没有就返回final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();if (lifecycleItem == null) {// No lifecycle request, return early.return;}......// 重点* 将Activity的状态转换至接近最终目标状态的位置 也就是会触发onStartcycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);// Execute the final transition with proper parameters.// 当前场景是触发LaunchActivityItem的executelifecycleItem.execute(mTransactionHandler, token, mPendingActions);lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);}
而之前SystemService对这2个事务的处理如下:
ActivityTaskSupervisor::realStartActivityLockedLaunchActivityItem.obtain -- 添加到事务到 mActivityCallbacks 列表ResumeActivityItem.obtain -- 设置事务到 mLifecycleStateRequestClientLifecycleManager::scheduleTransaction -- 触发事务的执行
所以说:executeCallbacks 方法是处理 LaunchActivityItem,executeLifecycleState 是处理 ResumeActivityItem。
2.4 小结
经过上面这些分析,我们知道在 ActivityTaskSupervisor::realStartActivityLocked 方法中启动 Activity 就是构建了2个事务到 ClientTransaction 中,并跨进程到目标进程执行。
2个事务从SystemService进程到目标应用进程完整的调用链如下:
ActivityTaskSupervisor::realStartActivityLockedClientTransaction::obtain -- 构建客户端事务LaunchActivityItem::obtain -- 构建 onCreate 启动事务ClientTransaction::addCallback -- onCreate事务添加进回调ResumeActivityItem::obtain -- 构建 onResume 事务ClientTransaction::setLifecycleStateRequest -- onResume 事务添加进LifecycleStateRequestClientLifecycleManager::scheduleTransaction -- 执行事务ClientTransaction::schedule -- 触发目标进程执行ActivityThread$ApplicationThread::scheduleTransaction -- 进入应用进程ClientTransactionHandler::scheduleTransactionClientTransaction::preExecuteActivityThread::sendMessage -- 发送“EXECUTE_TRANSACTION”消息ActivityThread$H::handleMessage TransactionExecutor::executeTransactionExecutor::executeCallbacks -- LaunchActivityItem 事务LaunchActivityItem::execute -- 触发 onCreateLaunchActivityItem::postExecuteTransactionExecutor::executeLifecycleState -- ResumeActivityItem 事务TransactionExecutor::cycleToPath -- 触发 onStartResumeActivityItem::execute -- 触发 onResumeResumeActivityItem::postExecute
时序图如下:
可以看到从 生命周期事务的执行到真正触发其 execute 方法,中间的调用链还是很长的,不过这个流程也不算很重要,一般看到 ResumeActivityItem 这种事务构建了,直接去看对应的 execute,postExecute 等方法就好了。
从调用链上也看到了 3个生命周期的执行顺序和期望的log打印也是一样的,当然具体是怎么执行到的要看后续代码分析。
3. 总结
这一篇对介绍了 Activity 启动流程中 SystemService 端末尾的工作,
另外介绍了一下 Activity 生命周期事务跨进程处理方式,关于onCreate,onStart,onResume 这3个生命周期在SystemService 端的流程介绍完了,下一篇是重点,会详细介绍在应用端对这3个生命周期的处理流程。
相关文章:

【Android 13源码分析】Activity生命周期之onCreate,onStart,onResume-1
忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。 – 服装…...

达梦数据库开启归档模式
目录 一、什么是归档模式? 二、开启归档模式的步骤 1、创建归档目录 2、进入dm数据库bin目录 3、登录数据库 4、关闭数据库 5、启动数据库到Mount状态 6、增加本地归档日志文件 7、开启归档 8、启动数据库 9、验证是否开启成功 三、开启归档模式的优…...
C++ 语言特性07 - 静态成员的初始化
一:概述 1. 静态成员变量通常在类定义内部声明,并在类定义外部定义和初始化。 class MyClass { public:static int staticVar; // 声明 };int MyClass::staticVar 42; // 定义和初始化 2. 从C11开始,可以在类内直接初始化静态数据成员&am…...

【数据结构】图论基础
文章目录 图的概念图的基本概念图的类型图的表示方法 图的相关基本概念1. 路径(Path)2. 连通性(Connectivity)3. 图的度(Degree)4. 子图(Subgraph)5. 生成树(Spanning Tr…...

HTML5实现好看的唐朝服饰网站模板源码2
文章目录 1.设计来源1.1 网站首页1.2 唐装演变1.3 唐装配色1.4 唐装花纹1.5 唐装文化 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板,程序开发,在线开发,在线沟通 作者:xcLeigh 文章地址:https://blog.csdn.ne…...

golang web笔记-2.请求request
什么是request http消息分为request(请求) 和 response(响应) request:在go中是一个struct,代表了客户段发送的http请求,已可以通过request 的方法访问请求中的cookie、URL、User Agent…...
docker的安装与启动——配置国内Docker源
移除旧版本docker sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine 配置docker yum源。 sudo yum install -y yum-utils sudo yum-config-manager –add-repo ht…...

httpsok-v1.17.0-SSL通配符证书自动续签
🔥httpsok-v1.17.0-SSL通配符证书自动续签 介绍 httpsok 是一个便捷的 HTTPS 证书自动续签工具,基于全新的设计理念,专为 Nginx 、OpenResty 服务器设计。已服务众多中小企业,稳定、安全、可靠。 一行命令,一分钟轻…...
相机、镜头参数详解以及相关计算公式
一、工业相机参数 1、分辨率 相机每次采集图像的像素点数,也是指这个相机总共有多少个感光晶片。在采集图像时,相机的分辨率对检测精度有很大的影响,在对同样打的视场成像时,分辨率越高,对细节的展示越明显。 相机像素…...

【微服务】组件、基础工程构建(day2)
组件 服务注册和发现 微服务模块中,一般是以集群的方式进行部署的,如果我们调用的时候以硬编码的方式,那么当服务出现问题、服务扩缩容等就需要对代码进行修改,这是非常不好的。所以微服务模块中就出现了服务注册和发现组件&…...

ESP32微信小程序SmartConfig配网
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 ESP32&微信小程序SmartConfig配网 前言一、SmartConfig是什么?二、使用乐鑫官方的smart_config例子1.运行照片 三、微信小程序总结 前言 本人是酷爱ESP32S3这…...
【PostgreSQL】提高篇——深入了解不同类型的 JOIN(INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN)应用操作
1. JOIN 的基础概念 在 SQL 中,JOIN 是用于从两个或多个表中组合行的操作。JOIN 允许我们根据某些条件将表中的数据关联在一起。常见的 JOIN 类型包括: INNER JOIN:仅返回两个表中满足连接条件的行。LEFT JOIN(或 LEFT OUTER JO…...

师生健康信息管理:SpringBoot技术突破
第4章 系统设计 4.1 系统体系结构 师生健康信息管理系统的结构图4-1所示: 图4-1 系统结构 登录系统结构图,如图4-2所示: 图4-2 登录结构图 师生健康信息管理系统结构图,如图4-3所示。 图4-3 师生健康信息管理系统结构图 4.2…...

【完-网络安全】Windows注册表
文章目录 注册表启动项及常见作用五个根节点常见入侵方式 注册表 注册表在windows系统的配置和控制方面扮演了一个非常关键的角色,它既是系统全局设置的存储仓库,也是每个用户的设置信息的存储仓库。 启动项及常见作用 快捷键 WinR打开运行窗口&#x…...

车辆重识别(2021NIPS在图像合成方面,扩散模型打败了gans网络)论文阅读2024/10/01
本文在架构方面的创新: ①增加注意头数量: 使用32⇥32、16⇥16和8⇥8分辨率的注意力,而不是只使用16⇥16 ②使用BigGAN残差块 使用Big GAN残差块对激活进行上采样和下采样 ③自适应组归一化层 将经过组归一化操作后的时间步和类嵌入到每…...

掌控物体运动艺术:图扑 Easing 函数实践应用
现如今,前端开发除了构建功能性的网站和应用程序外,还需要创建具有吸引力且尤为流畅交互的用户界面,其中动画技术在其中发挥着至关重要的作用。在数字孪生领域,动画的应用显得尤为重要。数字孪生技术通过精确模拟现实世界中的对象…...

Python从入门到高手4.2节-掌握循环控制语句
目录 4.2.1 理解循环控制 4.2.2 for循环结构 4.2.3 循环结构的else语句 4.2.4 while循环结构 4.2.5 循环结构可以嵌套 4.2.6 国庆节吃好玩好 4.2.1 理解循环控制 我们先来搞清楚循环的含义。以下内容引自汉语词典: 循环意指往复回旋,指事物周而复始地运动或变…...
CSS 中的overscroll-behavior属性
overscroll-behavior 是 CSS 中的一个属性,它用于控制元素在发生滚动时,当滚动范围超出其边界时的行为。这个属性对于改善用户体验特别有用,尤其是在移动端设备上,当用户尝试滚动一个已经达到滚动极限的元素时,可以通过…...
GPT对话知识库——在STM32的平台下,通过SPI读取和写入Flash的步骤。
目录 1,问: 1,答: 步骤概述 步骤 1:SPI 初始化 步骤 2:Flash 初始化(可选) 步骤 3:发送读取命令 示例:发送读取数据命令 步骤 4:读取数据…...
Pytorch基本知识
model.state_dict()、model.parameters()和model.named_parameters()的区别 parameters()只包含模块的参数,即weight和bias(包括BN的)。 named_parameters()返回包含模块名和模块的参数的列表,列表的每个元素均是包含layer name和layer param的元组。layer param就是param…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...

【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...