启动框架 Anchors接入和分析

news2024/11/26 18:18:43

参考:

https://juejin.cn/post/6844904128443858958

https://blog.csdn.net/gqg_guan/article/details/127760207

从哪下手

整个冷启动过程中,系统方法我们无法进行优化,主要需要优化的是系统暴露出来的一些生命周期方法,从Application的attachBaseContext开始,到启动页Activity或者首页Activity的onResume结束,甚至直到Activity的界面绘制结束。优化的目的就是使这个过程尽量快,不要出现卡顿。其中最重要的就是Application中的onCreate方法了。

初始化任务分析

  • 将初始化任务按两个维度区分:是否耗时&是否必要。必要且耗时的,考虑使用其他线程来初始化(比如Tinker初始化),不必要的都延迟启动。

初始任务的状态:

采用任务优化后的状态:

UML类图

使用方式

  • 要执行一个任务,需要自定义Task(继承BaseTask)。

  • 使用自定义工厂创建对应的Task,工厂继承自Project.TaskFactory。

  • 使用Project.Builder创建Task图。

  • 使用AnchorsManager的start方法启动Task(BaseTask的start方法是protected修饰的)

  • 在Demo中,在Application的onCreate方法中调用以下代码启动整个过程。

MainProcessStarter.start(checkPermission);
  • 更多注释都在代码中

BaseTask
  • BaseTask是一个任务单元,其中定义了前置任务dependTasks与后置任务behindTasks,每个Task会有优先级,锚点任务优先级是最高的,优先级主要用来排序。

  • 当向taskB中加入一个前置条件taskA时,taskA会被加入taskB的前置任务dependTasks,同时taskB也会被加入taskA的后置任务behindTasks中。

  • 当向taskB中加入一个后置条件taskC时,taskC会被加入taskB的后置任务behindTasks,同时taskB也会被加入taskC的前置任务dependTasks中。

  • 当一个task执行完成时,会将自己的后置任务behindTasks逐个启动,此时后置的任务会判断自己还有没有前置的任务,如果有就不执行,没有才执行。

Project
  • Project的存在意义在于他的Builder,他能构造一个不会产生环的task图。

AnchorsManager
  • BaseTask是不能直接调用start方法执行的,必须通过AnchorsManager的start才能执行,它定义了如何正确地执行一个task。

  • 从start方法可以看出,锚点任务都会在start所在方法内执行完(比如说我在onCreate中调用了start,则锚点任务都会在onCreate方法中执行)

AnchorsRuntime
  • 会对整个执行过程记录信息,并打印出log

  • 管理着一个线程池,用于执行异步任务

为什么会变快

首先看到每个task的启动方法start

/**
 * 调用start启动当前task
 */
protected synchronized void start() {
    if (mState != TaskState.IDLE) {
        throw new RuntimeException("can no run task " + getId() + " again!");
    }
    toStart();
    setExecuteTime(System.currentTimeMillis());
    AnchorsRuntime.executeTask(this);
}
复制代码

最终都会调用到AnchorsRuntime.executeTask(this);,如下:

/**
 * 同步使用handler发送至主线程,异步使用线程池
 * @param task 任务
 */
static void executeTask(BaseTask task) {
    if (task.isAsyncTask()) {
        S_POOL.executeTask(task);
    } else {
        if (AnchorsRuntime.hasAnchorTasks()) {
            AnchorsRuntime.addRunTasks(task);
        } else {
            sHandler.post(task);
        }
    }
}
复制代码

首先异步执行当然会减少启动时间,那如果全部都是同步执行呢?经过测试,启动过程也是变快了的。最终启动变快的原因就在于这个sHandler.post(task);(sHandler的Looper是主线程的Looper)。当每个task执行时,会post到主线程的消息队列的末尾,相当于不是立即执行,而是等待主线程现有的任务执行完了才执行,相当于给App启动“让路”。

systrace分析

在Demo中,START_TASK_3、START_FIRST_OF_ALL是锚点任务,START_TASK_3 depend on START_CONFIG_PRELOAD,任务图是在Application的onCreate中执行的,所以这三个任务会在onCreate中执行完毕,如下图:

继续往后看,START_TASK_2在启动页的Resume之后执行了,因为它post的时候,ActivityThread.H(主线程Handler)已经把LaunchActivity、ResumeActivity的message发送给了主线程任务队列。

最后这张图是剩下的任务执行过程,可以参看Demo的代码进行比对。Demo中分了Project1与Project2,前者是不需要申请权限的,后者需要,在他们之间有一个AwaitPermStartTask,可以阻塞整个任务图的执行,等待用户授权后在继续执行需要授权的任务(从图中的p2_start开始)。具体原理是使用CountDownLatch进行阻塞,使用RxBus进行回调。

从整体来看,本来全在Application的onCreate中执行的任务大部分都后移了,App启动的任务会被稍微“提前”,对于部分任务,更是在MainAcitivty启动之后才执行的,所以达到了优化的效果。但是这种方法也会有缺点,这些后移的任务如果需要在主线程执行,可能会影响到界面的绘制,造成卡顿,可以考虑使用MessageQueue.IdleHandler,在主线程空闲的时候执行剩下的任务。

用数据说话

最后,经过测试Demo,启动速度从900ms多加速到650ms左右,大约提速30%(从Application的attachBaseContext开始计时,直到MainActivity的onWindowFocusChanged)(ps:这里的耗时都是我自定义的,所以真正的优化效果还要看具体情况)

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

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

相关文章

OSCP学习踩过的坑

OSCP终于拿到证,感觉参加考试备考的日子才过去没有多久,想起了那几个月被“虐待”的日子,我想总结下在课程和考试中的犯的错误! 计划 我制定了一个学习计划,计划是学习、练习,然后再学习、练习一些&#…

SpringCloud:服务拆分及远程调用

目录 SpringCloud:服务拆分及远程调用 1、服务拆分 2、远程调用 SpringCloud:服务拆分及远程调用 SpringCloud是目前国内使用最广泛的微服务框架。 官网地址: Spring Cloud SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了…

【10】SCI易中期刊推荐——工程技术-计算机:人工智能(中科院2区)

🚀🚀🚀NEW!!!SCI易中期刊推荐栏目来啦 ~ 📚🍀 SCI即《科学引文索引》(Science Citation Index, SCI),是1961年由美国科学信息研究所(Institute for Scientific Information, ISI)创办的文献检索工具,创始人是美国著名情报专家尤金加菲尔德(Eugene Garfield…

JAVA开发(Eureka基本原理)

Eureka基本原理。 通过上图我们可以看出,服务提供者在启动的时候需要向注册中心注册自己的信息,而注册中心把向自己注册的服务提供者都保存下来,以便服务消费者获取用来发起请求,而服务消费者需要从注册中心获取服务提供者列表&am…

网络层:IP协议

目录 基本概念 IP报头 IP报文分片 为什么要分片? 如何分片? 分片的报文如何组装? 分片策略如何? 网段划分 IP地址被分成了五类IP: CIDR 特殊的IP地址: 私有IP和公网IP 路由 如何转发数据包&a…

「ABAP」一文带你入门OPEN SQL中的SELECT查询(附超详细案例解析)

💂作者简介: THUNDER王,一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学会计学专业大二本科在读,同时任汉硕云(广东)科技有限公司ABAP开发顾问。在学习工作中,我通常使用偏后…

阿里云服务器价格,阿里云轻量应用服务器最新价格表

阿里云服务器从地域上来区分可分为ECS云服务器和轻量应用服务器,从活动内容来区分又可分为秒杀云服务器和新用户特惠云服务器,下面是截止目前,阿里云服务器最新的秒杀及新用户特惠购买价格,以表格形式形式展示出来以供参考。 阿里…

​ICLR 2023 | 图数据分布外检测:从能量模型出发

©PaperWeekly 原创 作者 | 吴齐天单位 | 上海交通大学博士生研究方向 | 机器学习与图深度学习继续探索 Graph OOD 的相关问题,与以往工作不同的是,这篇工作避开了复杂的数学推导和琐碎的数据生成过程,直接从简单有效的判别模型入手研究…

【Spring】掌握 Spring Validation 数据校验

个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~ Spring Validation 数据校验一、什么是 Spring…

RAN-in-the-Cloud:为 5G RAN 提供云经济性

RAN-in-the-Cloud:为 5G RAN 提供云经济性 5G 部署在全球范围内一直在加速。 许多电信运营商已经推出了5G服务并正在快速扩张。 除了电信运营商之外,企业也对使用 5G 建立私有网络产生了浓厚的兴趣,这些私有网络利用了更高的带宽、更低的延迟…

【编程基础之Python】8、Python复合数据类型

【编程基础之Python】8、Python复合数据类型Python复合数据类型列表(List)创建列表访问元素内置方法列表操作元组(Tuple)创建元组访问元素集合(Set)创建集合基本操作其他操作字典(Dictionary&am…

4.ffmpeg命令转码规则、过滤器介绍、手动流map选项

在上章我们学习了ffmpeg命令行帮助以及选项查找 本章我们来深入学习ffmpeg命令转码规则、过滤器介绍、手动流map选项 参考链接: 1.ffmpeg命令行转码流程 ffmpeg命令行转码流程如下图所示: 对应中文则是: 步骤如下所示: ffmpeg调用libavformat库(包含解复用器)来读取输入文件…

Linux -- 查看进程 PS 命令 详解

我们上篇介绍了, Linux 中的进程等概念,那么,在Linux 中如何查看进程呢 ??我们常用到的有两个命令, PS 和 top 两个命令,今天先来介绍下 PS 命令~!PS 命令 :作用 &#x…

C语言拔高知识——指针的进阶(万字大文超详细)

在之前的文章中,我已经讲解过了初阶指针的内容,今天就来讲一讲指针的进阶! 上篇指针地址:保姆式指针讲解,超详细,适合初学者_指针详解_陈大大陈的博客-CSDN博客 目录 1. 字符指针 2. 指针数组 3. 数组指…

3年测试经验的人来面试,简历都没写明白,一开口就要给20K的offer?

​我最近阅读了大约15份简历,他们都在申请我的团队的测试工程师职位。但是没有一份表达清楚了他是如何进行测试的。 下面我摘录了一些 信息: 几乎所有的应聘者都罗列了成串儿的他们熟悉的“技术”(包括但不限于….Net, Unix&#…

c++基础/类和对象

c基础 2.1名字空间 namespace 防止命名冲突 说明&#xff1a;名字空间可以在全局作用域或其他作用域&#xff08;另一个名字空间&#xff09;内部定义&#xff0c;但不能在函数或类的内部定义。 使用&#xff1a; #include<iostream> using namespace std; //std中包…

【C/C++ 数据结构】-八大排序之 冒泡排序快速排序

作者&#xff1a;学Java的冬瓜 博客主页&#xff1a;☀冬瓜的主页&#x1f319; 专栏&#xff1a;【C/C数据结构与算法】 分享&#xff1a;那我便像你一样&#xff0c;永远躲在水面之下&#xff0c;面具之后&#xff01; ——《画江湖之不良人》 主要内容&#xff1a;八大排序选…

前端构建工具大盘点:gulp、webpack、vite、rollup、esbuild、snowpack、babel、parcel、swc、tsc

文章目录背景分类转译器打包器对比gulp VS webpackBundle vs Bundleless&#xff08;代表就是webpack VS vite&#xff09;其他比较个人理解总结官网背景 做前端也有好多年了&#xff0c;从最早的 jQuery 时代到现在的三大框架&#xff0c;这过程中用到了很多构建工具&#xf…

婴幼儿常见八大疾病及护理方法

在1岁之前&#xff0c;婴儿的体质还没有完全发育&#xff0c;很容易生病&#xff0c;大多数婴儿在1岁之后都会更好。今天&#xff0c;新的稀有婴儿育儿专家组织了一些婴儿最容易患的疾病和护理方法。1、新生儿黄疸宝宝出生后&#xff0c;你可能会注意到他的皮肤发黄。别担心&am…

Netty学习(三):Netty线程模型和代码示例

〇、前言网络编程的基本线程模型&#xff0c;详见&#xff1a;Netty学习&#xff08;二&#xff09;&#xff1a;线程模型一、工作原理简图Netty主要基于主从 Reactors 多线程模型&#xff08;如下图&#xff09; 做了一定的改进&#xff0c;其中主从Reactor 多线程模型有多个R…