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

news2024/10/1 23:03:51

忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。
                  
                  
                                           – 服装学院的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.
                // 不满足添加就打log
                ProtoLog.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逻辑,启动走的这。 表示需要执行到onCreate
                    lifecycleItem = 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;
        // 目标Activity
        private IBinder mActivityToken;

        // client :对应进程
        // activityToken :创建ActivityRecord时的匿名token
        public 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 方法是如何触发对应事务执行的。

该方法有多个重载,但是本质都一样


# ClientLifecycleManager
    void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();
        // 重点* 调用ClientTransaction::schedule
        transaction.schedule();
        ......
    }

    void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
            @NonNull ActivityLifecycleItem stateRequest) throws RemoteException {
        //  构建 一个 ClientTransaction,调用上面的scheduleTransaction
        final ClientTransaction clientTransaction = transactionWithState(client, activityToken,
                stateRequest);
        scheduleTransaction(clientTransaction);
    }
    ......忽略另外几个重载, 都是内部构建出一个 ClientTransaction 

主要就是执行了 ClientTransaction::schedule 方法。

2.3 应用进程处理

ClientTransaction::schedule 方法会跨进程调用到目标进程的 scheduleTransaction 方法,我们知道进程指的就是 ActivityThread 内部类 ApplicationThread

# ActivityThread$ApplicationThread
        @Override
        public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            // 这里调用的是ActivityThread的父类 ClientTransactionHandler
            ActivityThread.this.scheduleTransaction(transaction);
        }

# ClientTransactionHandler
    void scheduleTransaction(ClientTransaction transaction) {
        // 执行 preExecute (预执行)
        transaction.preExecute(this);
        // 重点* 发送消息
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }

先执行 preExecute 方法,最重要的是执行发送了一个 EXECUTE_TRANSACTION 消息,并把 ClientTransaction 传过去了。

这个消息的处理在 ActivityThread 中。

# ActivityThread
    private 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 中处理了。

# TransactionExecutor
    public void execute(ClientTransaction transaction) {
        ......
        // LaunchActivityItem
        executeCallbacks(transaction);

        // ResumeActivityItem
        executeLifecycleState(transaction);
        ......
    }

2.3.1 executeCallbacks 和 executeLifecycleState 方法

为什么我在上面注释里说 executeCallbacks 是处理 LaunchActivityItem,executeLifecycleState 是处理 ResumeActivityItem 呢?
代码中有答案:

# TransactionExecutor
    public 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的状态转换至接近最终目标状态的位置  也就是会触发onStart
        cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);

        // Execute the final transition with proper parameters.
        // 当前场景是触发LaunchActivityItem的execute
        lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
    }

而之前SystemService对这2个事务的处理如下:

ActivityTaskSupervisor::realStartActivityLocked
    LaunchActivityItem.obtain   -- 添加到事务到 mActivityCallbacks 列表
    ResumeActivityItem.obtain   -- 设置事务到 mLifecycleStateRequest
    ClientLifecycleManager::scheduleTransaction  -- 触发事务的执行

所以说:executeCallbacks 方法是处理 LaunchActivityItem,executeLifecycleState 是处理 ResumeActivityItem。

2.4 小结

经过上面这些分析,我们知道在 ActivityTaskSupervisor::realStartActivityLocked 方法中启动 Activity 就是构建了2个事务到 ClientTransaction 中,并跨进程到目标进程执行。

2个事务从SystemService进程到目标应用进程完整的调用链如下:

ActivityTaskSupervisor::realStartActivityLocked
    ClientTransaction::obtain             -- 构建客户端事务
    LaunchActivityItem::obtain            -- 构建 onCreate 启动事务
    ClientTransaction::addCallback        -- onCreate事务添加进回调
    ResumeActivityItem::obtain            -- 构建 onResume 事务
    ClientTransaction::setLifecycleStateRequest  --  onResume 事务添加进LifecycleStateRequest
    ClientLifecycleManager::scheduleTransaction  -- 执行事务
        ClientTransaction::schedule               -- 触发目标进程执行
            ActivityThread$ApplicationThread::scheduleTransaction  -- 进入应用进程
                ClientTransactionHandler::scheduleTransaction
                    ClientTransaction::preExecute
                    ActivityThread::sendMessage                     -- 发送“EXECUTE_TRANSACTION”消息
                        ActivityThread$H::handleMessage 
                            TransactionExecutor::execute
                                TransactionExecutor::executeCallbacks        -- LaunchActivityItem 事务
                                    LaunchActivityItem::execute              -- 触发 onCreate
                                    LaunchActivityItem::postExecute
                                TransactionExecutor::executeLifecycleState   -- ResumeActivityItem 事务
                                    TransactionExecutor::cycleToPath         -- 触发 onStart
                                    ResumeActivityItem::execute              -- 触发 onResume
                                    ResumeActivityItem::postExecute

时序图如下:
在这里插入图片描述
可以看到从 生命周期事务的执行到真正触发其 execute 方法,中间的调用链还是很长的,不过这个流程也不算很重要,一般看到 ResumeActivityItem 这种事务构建了,直接去看对应的 execute,postExecute 等方法就好了。

从调用链上也看到了 3个生命周期的执行顺序和期望的log打印也是一样的,当然具体是怎么执行到的要看后续代码分析。

3. 总结

这一篇对介绍了 Activity 启动流程中 SystemService 端末尾的工作,
另外介绍了一下 Activity 生命周期事务跨进程处理方式,关于onCreate,onStart,onResume 这3个生命周期在SystemService 端的流程介绍完了,下一篇是重点,会详细介绍在应用端对这3个生命周期的处理流程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2183325.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5款惊艳全网的AI写作论文神器!从此告别写作烦恼!

在当今的学术研究和写作领域&#xff0c;撰写高质量的论文是一项挑战性的任务。幸运的是&#xff0c;随着人工智能技术的发展&#xff0c;AI论文写作工具逐渐成为帮助学者和学生提高写作效率的重要工具。这些工具不仅能够提高写作效率&#xff0c;还能帮助研究者生成高质量的论…

ECharts 快速使用

最终效果 使用介绍 echarts图表的绘制&#xff0c;大体分为三步&#xff1a; 根据 DOM实例&#xff0c;通过 echarts.init方法&#xff0c;生成 echarts实例构建 options配置对象&#xff0c;整个echarts的样式&#xff0c;皆有该对象决定最后通过实例.setOption方法&#xf…

【测试-BUG篇】软件测试的BUG知识你了解多少呢?

文章目录 1. 软件测试的生命周期2. BUG3. BUG的生命周期4. 与开发人员起争执怎么办 1. 软件测试的生命周期 &#x1f34e;软件测试 贯穿整个软件的生命周期&#xff1b; &#x1f34e;软件测试的生命周期是指测试流程&#xff1b; ①需求分析 用户角度&#xff1a;软件需求是…

C++:一文搞懂友元类(friend class)

C的友元&#xff08;friend&#xff09;是个很重要的概念&#xff0c;好些朋友对此却很迷惑&#xff0c;本文将对友元类&#xff08;friend class&#xff09;详细讲解&#xff0c;一文搞懂。 友元的特性&#xff1a; 1、使用friend修饰的友元类可以访问本类的私有成员(priva…

中国电信解锁万亿参数大模型:TeleAI的创新与突破

首个由万卡集群训练出来的万亿参数大模型&#xff0c;已被一家央企解锁。 具体而言&#xff0c;为了推动纯国产人工智能的探索&#xff0c;带来这条新路径的正是中国电信人工智能研究院&#xff08;TeleAI&#xff09;。 该研究院由中国电信集团的CTO、首席科学家兼院长李学龙…

坡印廷矢量(也叫功率流密度,对面积积分就是功率)

坡印廷矢量在静电场&#xff0c;静磁场&#xff0c;恒定电流的电场&#xff0c;和时变电磁场中的表达式不同。 我们看时变电磁场的坡印廷矢量 坡印廷矢量就等于这个&#xff0c;其中的电场和磁场是实数表示的 坡印廷矢量用复数形式的场求 这里的E和H是复数表示的场&#xff0…

电影票接口api对接有哪些优势?

一、业务功能拓展方面的优势 多平台整合可以整合多个影院票务系统&#xff0c;通过一个接口获取众多影院的信息&#xff0c;包括影院、影厅、座位、影片、场次、日期及票价等信息&#xff0c;方便在自己的应用程序中展示这些信息&#xff0c;从而实现电影票的在线预订、支付和…

人工智能价格战——如何降低成本让人工智能更易于普及

十年前&#xff0c;开发人工智能 (AI) 是只有大公司和资金充足的研究机构才能负担得起的事情。必要的硬件、软件和数据存储成本非常高。但从那时起&#xff0c;情况发生了很大变化。一切始于 2012 年的 AlexNet&#xff0c;这是一种深度学习模型&#xff0c;展示了神经网络的真…

微服务jvisualvm解析部署使用全流程

1、介绍 VisualVM 是Netbeans的profile 2、启动 进入正在使用的jdk下bin目录&#xff0c;运行jvisualvm.exe。 3、选中要监控的线程 4、安装gc插件 5、插件安装报错 VisualVM: Plugins Centers 访问这个地址&#xff0c;找到对应版本再配置 https://visualvm.github.io/uc/…

【CKA】六、四层负载-Service应用

6、四层负载-Service应用 1. 考题内容&#xff1a; 2. 答题思路&#xff1a; 1、编辑front-end的deploy服务&#xff0c;添加端口信息 2、暴露svc端口 3. 官网地址&#xff1a; https://kubernetes.io/zh-cn/docs/tutorials/services/connect-applications-service/#the-ku…

nominatim部署OSM离线地图

第一步&#xff1a;准备一个大内存的服务器&#xff0c;磁盘PG大小根据实际导入的数据确定&#xff0c;全量数据1T&#xff0c;osm.pdf属于压缩文件&#xff0c;如果能下载&#xff0c;但下载很慢&#xff0c;可以尝试用迅雷下载。 osm.pdf下载 osm.pdf另外一个下载路径 全量数…

学生党有福了!国内最好的4款AI论文润色机构

在当今学术研究和写作领域&#xff0c;AI技术的应用已经变得越来越普遍。AI论文润色工具不仅能够帮助研究人员快速生成论文草稿&#xff0c;还能进行内容优化、查重和排版等操作。这些工具极大地提高了写作效率和质量&#xff0c;尤其对于学生党来说&#xff0c;选择合适的AI论…

基于单片机多功能称重系统设计

** 文章目录 前言概要功能设计设计思路 软件设计效果图 程序文章目录 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对…

2024年3分钟手把手教你激活Guitar Pro 8破解版

Guitar Pro是一款专业的吉他制谱软件&#xff0c;现在已更新至Guitar Pro8&#xff0c;新增了支持添加音频轨道、支持嵌套连音符、直观的效果器视图、让指法一目了然的音阶示意图等实用新功能。下面我们来看Guitar Pro8 Windows如何安装激活。 GuitarPro8安装包和许可证密钥夸克…

Acwing 高斯消元

高斯消元能在 O ( n 3 ) O(n^3) O(n3)的时间复杂度内求解n个方程&#xff0c;n个未知数的多元线性方程组&#xff0c;即 a 11 x 1 a 12 x 2 a 13 x 3 ⋯ a 1 n x n b 1 a 21 x 1 a 22 x 2 a 23 x 3 ⋯ a 2 n x n b 2 … a n 1 x 1 a n 2 x 2 a n 3 x 3 ⋯ a n n…

STM32CubeMX工程printf问题

1、不能打印输出的问题 利用STM32CubeMX创建了一个带FreeRTOS系统的工程&#xff0c;使能多线程保护。 然后在任务函数中调用了printf函数。 可是电脑的串口上没有信息输出&#xff0c;程序进入了硬件错误中断。 原来是因为自动生成的串口初始化函数MX_LPUART1_UART_Init中&a…

话术挂断之后是否处理事件

文章目录 前言联系我们解决方案方案一方案二 前言 流程&#xff1a;自动外呼进入机器人话术。问题&#xff1a;在机器人放音时用户挂断后&#xff0c;话术还会继续匹配流程&#xff0c;如果匹配上的是放音节点&#xff0c;还会进行放音&#xff0c;那么在数据库表conversation…

利用vue-capper封装一个可以函数式调用图片裁剪组件

1. 效果 const cropData await wqCrop({prop:{img,autoCrop: true, // 是否开启截图框maxImgSize: 600,autoCropWidth: 30,canMove: true, // 图片是否可移动canMoveBox: true, // 截图框是否可移动fixedBox: false, // 截图框是否固定}});console.log(cropData);使用wqCrop会…

阿里大模型算法岗面试,上来就手撕代码啊

最近已有不少大厂都在秋招宣讲了&#xff0c;也有一些在 Offer 发放阶段。 节前&#xff0c;我们邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对新手如何入门算法岗、该如何准备面试攻略、面试常考点、大模型技术趋势、算法项目落地经验分享等热门话题进行了…

Python | Leetcode Python题解之第440题字典序的第K小数字

题目&#xff1a; 题解&#xff1a; class Solution:def getSteps(self, cur: int, n: int) -> int:steps, first, last 0, cur, curwhile first < n:steps min(last, n) - first 1first * 10last last * 10 9return stepsdef findKthNumber(self, n: int, k: int)…