【Android 13源码分析】Activity生命周期之onCreate,onStart,onResume-1

news/2024/10/4 7:38:55/

忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。
                  
                  
                                           – 服装学院的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个必要条件:

    1. TargetActivity 所在的应用进程已经启动
    1. 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);}
    1. 如果有Activity没有执行完 pause ,则不能执行新的Activity的启动。 如果不满足条件也会相应的ProtoLog
    1. 打印Events日志,格式为:wm_restart_activity: [0,253598020,21,com.google.android.dialer/.extensions.GoogleDialtactsActivity]
    1. 构建 LaunchActivityItem 事务,将会触发创建Activity,并执行到 onCreate
    1. 构建 ResumeActivityItem 事务,将会触发执行到Activity的 onResume
    1. 执行事务

后面的流程其实可以直接去看应用端这2个事务的执行,不过我对这中间的调用比较好奇,所以把生命周期跨进程调用事务的逻辑也梳理了一遍。对这块比较了解的可以跳过,直接看第三章生命周期相关的内容

2. Activity 生命周期事务跨进程处理方式详解

2.1 了解ClientTransaction

在 ActivityTaskSupervisor::realStartActivityLocked 方法中对跨进程执行生命周期事务的代码可以归纳为以下几步:

    1. 构建出 ClientTransaction
    1. 构建 onCreate 和 onResume对应的2个事务,并保存到 ClientTransaction 中
    1. 通过 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 方法的使用得出以下结论:

    1. ClientTransaction::obtain 构建出一个 ClientTransaction 对象,2个参数分别为目标进程,和目标Activity
    1. addCallback 方法会将 LaunchActivityItem 放到 内部的 mActivityCallbacks 列表中
    1. 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个生命周期的处理流程。


http://www.ppmy.cn/news/1534292.html

相关文章

LeetCode hot100---双指针专题(C++语言)

双指针 (1)快慢双指针 适用于使用双指针进行元素移动&#xff0c;覆盖(2)首尾双指针 计算区域面积&#xff0c;三数之和1、移动0 &#xff08;1&#xff09;题目描述以及输入输出 (1)题目描述: 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#…

opencv实战项目(三十):使用傅里叶变换进行图像边缘检测

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一&#xff0c;什么是傅立叶变换&#xff1f;二&#xff0c;图像处理中的傅立叶变换&#xff1a;三&#xff0c;傅里叶变换进行边缘检测&#xff1a; 一&#xff0c…

JavaScript 数组方法

数组(array)是按次序排列的一组值。每个值的位置都有编号(从0开始)&#xff0c;整个数组用方括号表示。两端的方括号是数组的标志。 var a["a","b","c"]; 除了在定义时赋值&#xff0c;数组也可以先定义后赋值。 var arr[];arr[1]"a"…

分治算法:谈一谈大规模计算框架 MapReduce 中的分治思想

分治算法:谈一谈大规模计算框架 MapReduce 中的分治思想 在当今大数据时代,处理大规模数据的需求日益增长。MapReduce 作为一种广泛应用的大规模计算框架,其核心思想正是分治算法。本文将深入探讨 MapReduce 中的分治思想,并通过具体案例进行说明。 一、分治算法概述 分…

【JavaScript】数组函数汇总

JavaScript数组函数是处理和操作数据的基础&#xff0c;对于JavaScript开发至关重要。函数式编程方法&#xff0c;如map()、filter()和reduce()&#xff0c;能够提高代码的简洁性和功能性。数据不可变性是现代JavaScript开发中的一个重要概念&#xff0c;函数如concat()和slice…

C语言 | Leetcode C语言题解之第454题四数相加II

题目&#xff1a; 题解&#xff1a; struct hashTable {int key;int val;UT_hash_handle hh; };int fourSumCount(int* A, int ASize, int* B, int BSize, int* C, int CSize, int* D, int DSize) {struct hashTable* hashtable NULL;for (int i 0; i < ASize; i) {for (…

二值图像的面积求取的两种方法及MATLAB实现

一、引言 面积在数字图像处理中经常用到&#xff0c;在MATLAB中&#xff0c;计算二值图像的面积通常可以通过两种主要方法实现&#xff1a;遍历法和直接利用bwarea函数。下面将分别介绍这两种方法的原理和相应的MATLAB代码示例。 二、遍历法计算二值图像面积的原理和MATLAB代码…

物联网智能项目研究

物联网&#xff08;IoT&#xff09;作为当今数字化转型的重要推动力&#xff0c;正在改变我们的生活方式和工作模式。从智能家居、智慧城市到工业自动化&#xff0c;物联网技术的应用正在实现人们对智能生活的向往。本文将探讨一个具体的物联网智能项目&#xff0c;通过实际操作…