当前位置: 首页 > news >正文

Android---启动速度优化

App 启动流程

1. 点击桌面 App 图标,Launcher 进程采用 Binder IPC 向 system_server 进程发起 startActivity 请求 ;

2. system_server 进程接收到请求后,向 zygote 进程发送创建进程的请求;

3. zygote 进程 fork 出新的子进程,即 App 进程

4. App 进程,通过 Binder IPC 向 system_server 进程发起 attachApplication 请求;

5. system_server 进程在收到请求后,进行一系列准备工作,再通过 binder IPC 向 App 进程发送 scheduleLaunchActivity 请求;

6. App 进程的 binder 线程(ApplicationThread)在收到请求后,通过 handler 向主线程发送 LAUNCH_ACTIVITY 消息;

7. 主线程收到 Message 后,通过反射机制创建目标 Activity,并回调 Activity.onCreate() 等方法;

8. 到此,App 便正式启动,开始进入 Activity 生命周期,执行完 onCreate/onStart/onResume 方法,UI 渲染结束后便可以看到 App 的主界面。

App 启动状态

应用有三种启动状态,每种状态都会影响应用向用户显示所需的时间:冷启动温启动热启动 

1. 冷启动:

冷启动是指应用从开头开始启动:系统进程在冷启动后才创建应用进程。发生冷启动的情况包括应用设备启动后系统终止应用首次启动

2. 热启动:

在热启动中,系统的所有工作就是将 Activity 带到前台。只要应用的所有 Activity 仍驻留在内存中,应用就不必重复执行对象初始化、布局加载和绘制。

3. 温启动:

温启动包含了在冷启动期间发生的部分操作;同时,它的开销要比热启动高。有许多潜在状态可视为温启动。例如:

        \bullet 用户在退出应用后又重新启动应用。进程可能未被销毁,继续运行,但应用需要执行 onCreate() 从头开始重新创建 Activity。

       \bullet 系统将应用从内存中释放,然后用户又重新启动它。进程和 Activity 需要重启,但传递到 onCreate() 的已保存的实例 savedInstanceState 对于完成此任务有一定助益。

冷启动耗时统计

在性能测试中存在启功时间 2-5-8 原则:

   \bullet 当用户能够在 2s 以内得到响应时,会感觉系统的响应很快;

   \bullet 当用户在 2-5s 之间得到响应时,会感觉系统的响应速度还可以;

   \bullet 当用户在 5-8s 之间得到响应,会感觉系统的响应速度很慢,但是还可以接受;

   \bullet 当用户在超过 8s 后仍无法得到响应,会感觉系统糟透了,或者认为系统已经失去响应。

而 Google 也提出一项计划:Android Vitals。该计划旨在改善 Android 设备的稳定性和性能。当选择启用了该计划的用户运行您的应用时,其 Android 设备会记录各种指标,包括应用稳定性、应用启动时间、电池使用情况、呈现时间和权限遭拒等方面的数据。Google Play 会汇报这些数据,并将其显示在 Android Vitals 信息中心内。

当应用启动时间过长时,Android Vitals 可以通过 Play 管理中心提醒您,从而帮助提升应用性能。Android Vitals 在您的应用出现以下情况时将启动时间视为过长:

   \bullet 冷启动用了 5s 或者更长时间。

   \bullet 温启动用了 2s 或者更长时间。

   \bullet 热启动用了 1.5s 或者更长时间。

实际上不同的应用因为启动时需要初始化的数据不同,启动时间自然也会不同,相同的应用也会因为在不同的设备,因为设备性能影响启动速度不同。所以实际上启动时间并没有绝对统一的标准,我们之所以需要进行启动耗时的统计,可能在于产品对我们应用启动时间提出具体的要求。

CPU Profile

如果发现显示时间比希望的时间长,则可以继续尝试识别启动过程中的瓶颈。查找瓶颈的一个好方法是使用 Android Studio CPU 性能解剖器。

要在应用启动过程中自动开始记录 CPU 活动,请执行以下操作:

步骤1:Run --> Edit Configurations

 

步骤2:在 Profiling 标签中,勾选 Start recording CPU on startup 旁边的复选框。

步骤3:从菜单中选择 CPU 记录配置。

 \bullet Java/Kotlin Method Sample(legacy)

对 java 方法采用:在应用的 Java 代码执行期间,频繁捕获应用的调用堆栈。分析器会比较捕获的数据集,以推导与应用的 Java 代码执行有关的时间或资源使用信息。如果应用在捕获调用堆栈后进入一个方法并在下次捕获前退出该方法,分析器将不会记录该方法调用。如果您想要跟踪生命周期如此短的方法,应使用检测跟踪。

 \bullet Java/Kotlin Method Trace

跟踪 Java 方法:在运行时检测应用,以在每个方法调用开始和结束时记录一个时间戳。系统会收集并比较这些时间戳,以生成方法跟踪数据,包括时间信息和 CPU 使用率。

 \bullet System Trace

跟踪系统调用:捕获非常详实的细节,以便您检查资源的交互情况。您可以检查线程状态的确切时间和持续时间、直观地查看所有内核的 CPU 瓶颈在何处,并添加要分析的自定义跟踪事件。要使用此配置,您必须将应用部署导搭载 Android 7.0(API 级别24)或更高版本的设备上。

此跟踪配置在 systrace 的基础上构建而成。您可以使用 systrace 命令行使用程序指定除 CPU Profiler 提供的选项之外的其他选项。systrace 提供的其他系统级数据可以帮助您检查原生系统进程并排查丢帧或帧延迟问题。

步骤4:点击 Apply

步骤5:依次选择 Run --> Profile,将您的应用部署导搭载 Android 8.0(API 级别 26) 或更高版本的设备上。

点击 Stop,结束跟踪后显示

 Call Chart 

以图形来呈现方法跟踪数据函数跟踪数据,其中调用的时间段和时间在横轴上表示,而其被调用方则在纵轴上显示。对系统 API 的调用显示为橙色,对自己写的方法的调用显示为绿色,对第三方 API(包括 Java 语言 API)的调用显示为蓝色

如上图,自定义 Application 的 onCreate 调用了 Thread.sleep 耗时为 3s。

Call Chart 已经比原始数据可读性高很多,但它仍然不方便发现那些运行时间很长的代码,这时我们便 需要使用 Flame Chart。

Flame Chart

提供一个倒置的调用图表,用来汇总完全相同的调用堆栈。也就是说,将具有相同调用、顺序完全相同的方法或函数收集起来,并在火焰图(Flame Chart)中将它们表示为一个较长的横条。

横轴显示的是百分比数值。由于忽略了时间线信息,Flame Chart 可以暂时每次调用消耗时间占用整个记录时长的百分比。同时纵轴也被对调了,在顶部展示的是被调用者,底部展示的是调用者。此时的图表看起来越往上越窄,就好像火焰一样,因此得名:火焰图

Top Down Tree

如果我们需要更精确的时间信息,就需要使用 Top Down Tree。Top Down Tree 显示一个调用列表,在该列表中展开方法或函数节点会显示它调用了的方法节点。

对于每个节点,三个时间信息:

 \bullet Self Time --运行自己的代码所消耗的时间;

 \bullet Children Time -- 调用其他方法的时间;

 \bullet Total Time -- 前面两者时间之和。

Bottom Up Tree

方便地找到某个方法的调用栈。在该列表中展开方法或函数节点会显示那个方法调用了自己。

 

布局优化

通过工具可以定位到耗时代码,然后查看是否可以进行优化。对于 App 启动来说,启动耗时包括 Android 系统启动 App 进程加上 APP 启动界面的耗时时长,我们可做的优化是 APP 启动界面的耗时,也就是说从 Application 的构建到主界面的 onWindowFocusChanged 的这一段时间。

因此在这段时间内,我们的代码需要尽量避免耗时操作,检查的方法包括:主线程I/O;第三方库初始化或程序需要使用的数据等初始化改为异步加载/懒加载;减少布局复杂度与嵌套层级;Multidex(5.0以上无需考虑)等。

加载布局文件也是一个耗时操作。对于布局的优化:嵌套的层级不要太深,控件不要太多

使用 AsyncLayoutInflater 对布局进行异步加载

StrictMode 严苛模式

希望:在开发阶段开启,在发布阶段关闭。

StrictMode 是一个开发人员工具,它可以检测出我们可能无意中做的事情,并用它们提醒我们注意,以便我们能够修复它们。StrictMode 最常用于捕获应用程序主线程上的意外磁盘或网络访问。帮助我们让磁盘和网络操作远离主线程,可以使应用程序更加平滑、响应更快。

public class MyApplication extends Application {@Overridepublic void onCreate() {if (BuildConfig.DEBUG) {//线程检测策略StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads() //读、写操作.detectDiskWrites().detectNetwork() // or .detectAll() for all detectable problems.penaltyLog().build());//虚拟机检测策略StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects() //Sqlite对象泄露.detectLeakedClosableObjects() //未关闭的Closable对象泄露.penaltyLog() //违规打印日志.penaltyDeath() //违规崩溃.build());}
}

启动优化的优化点

 \bullet 合理的使用异步初始化、延迟初始化、懒加载机制。

 \bullet 启动过程避免耗时操作,如数据库、I/O 操作等不要放在主线程。

 \bullet 类加载优化:提前异步执行类加载

 \bullet 合理使用 IdleHandler 进行延迟初始化

 \bullet 简化布局

相关文章:

Android---启动速度优化

App 启动流程 1. 点击桌面 App 图标,Launcher 进程采用 Binder IPC 向 system_server 进程发起 startActivity 请求 ; 2. system_server 进程接收到请求后,向 zygote 进程发送创建进程的请求; 3. zygote 进程 fork 出新的子进程…...

使用 Mercury 直接从 Jupyter 构建 Web 程序

动动发财的小手,点个赞吧! 有效的沟通在所有数据驱动的项目中都至关重要。数据专业人员通常需要将他们的发现和见解传达给利益相关者,包括业务领导、技术团队和其他数据科学家。 虽然传达数据见解的传统方法(如 PowerPoint 演示文…...

Python基础(二)

目录 一、类型转换 1、为什么需要数据类型转换 2、数据类型转化的函数 3、str()函数类型转换使用 4、int()函数类型转换使用 4.1int()不能将str类型数据转换成int 4.2int()将bool类型转换成int 4.3int()将float转换成int 5、Float()函数类型转换使用 5.1Float()函数不…...

第41讲:Python循环语句中的break-else语法结构

文章目录 1.在循环正常结束后执行动作的思路2.通过控制布尔值变量的方式在循环正常结束后执行某些操作2.1.while循环语句2.2.for-in循环语句3.通过else从句来执行某些操作1.在循环正常结束后执行动作的思路 在执行while循环语句或者for循环语句时,如果循环是正常结束的,非执…...

双系统-真机安装ubuntu

服务器系统最好选择legacy启动mbr硬盘,数据盘可以使用gpt格式,超过2t的只能用gpt。 华为2288v3用uefi找不到启动硬盘,或者是找到硬盘后无法引导,迁移系统得到有efi引导文件的硬盘也不行,选择用legacy吧。 ubuntu默认uefi启动,若使用legacy,则需要easybcd处理一下引导。 …...

Android实现向facebook回复消息代码

以下是一个示例代码,它基于Facebook SDK版本5.0,具体实现如下: 1. 集成Facebook SDK库 下载Facebook SDK并将其加入到Android Gradle构建文件中,像这样: groovy dependencies { implementation com.facebook.an…...

IDEA小技巧-Git的回滚强推代码找回

标题IDEA小技巧-Git的回滚&&强推&&代码找回 本地未Commit 新增文件 delete 变更文件 rollback 第一种方式 第二种方式 切换默认变更列表 Commit未push undo commit 仅适用于最后一次的提交进行回滚 drop commit 回滚 revert commit revert commi…...

即时通讯为什么不采用UDP的连接方式呢

即时通讯为什么不采用UDP的连接方式呢 博主今天从网络上找了几个比较关注的热点的内容进行讲解 1.首先介绍一下UDP连接的缺点 不可靠:UDP是一种无连接的传输协议,它不提供数据包的可靠传输保证。这意味着当使用UDP进行通信时,数据包可能会丢…...

二叉树(纲领篇)

文档阅读 文档阅读 二叉树解题的思维模式分两类: 1、是否可以通过遍历一遍二叉树得到答案?如果可以,用一个 traverse 函数配合外部变量来实现,这叫「遍历」的思维模式。 2、是否可以定义一个递归函数,通过子问题&a…...

day41—选择题

文章目录 1.某主机的IP 地址为 180.80.77.55,子网掩码为 255.255.252.0。若该主机向其所在子网发送广播分组,则目的地址可以是(D)2.ARP 协议的功能是(A)3.以太网的MAC 协议提供的是(A&#xff0…...

Vue3 watch 监听对象数组中对象的特定属性

在 Vue 3 中,可以使用 watch 函数来监听对象数组中对象的特定属性。可以通过在回调函数中遍历数组来检查对象的特定属性是否发生变化,并在变化发生时执行相应的操作。 一、监听对象的特定属性 例如,假设有一个名为 items 的对象数组&#x…...

请求策略库alova小记

官方文档地址:https://alova.js.org/zh-CN/get-started/overview 定义 alova是一个简单编码即可实现特定场景的高效请求的请求策略工具。 场景痛点 现在一般的请求场景,一般分为两个部分: 请求部分。一般用axios等库触发http请求&#xf…...

[C++]string的使用

目录 string的使用:: 1.string类介绍 2.string常用接口说明 string相关习题训练:: 1.仅仅反转字母 2.找字符串中第一个只出现一次的字符 3.字符串里面最后一个单词的长度 4.验证一个字符串是否是回文 5.字符串相加 6.翻转字符串…...

Kali Linux 操作系统安装详细步骤——基于 VMware 虚拟机

1. Kali 操作系统简介 Kali Linux 是一个基于 Debian 的 Linux 发行版,旨在进行高级渗透测试和安全审计。Kali Linux 包含数百种工具,适用于各种信息安全任务,如渗透测试,安全研究,计算机取证和逆向工程。Kali Linux 由…...

R语言APSIM模型应用及批量模拟实践技术

查看原文>>>基于R语言APSIM模型高级应用及批量模拟实践技术 目录 专题一、APSIM模型应用与R语言数据清洗 专题二、APSIM气象文件准备与R语言融合应用 专题三、APSIM模型的物候发育和光合生产模块 专题四、APSIM物质分配与产量模拟 专题五、APSIM土壤水平衡模块 …...

破解马赛克有多「容易」?

刷短视频时,估计大家都看过下面这类视频,各家营销号争相曝光「一分钟解码苹果笔刷背后内容」的秘密。换汤不换药,自媒体们戏称其为「破解马赛克」,殊不知让多少不明真相的用户建立起了错误的认知,也让苹果笔刷第 10086…...

【.NET基础加强第八课--委托】

.NET基础加强第八课--委托 委托(Delegate)委托操作顺序实例多播委托—委托链实例实例委托传值 委托(Delegate) 委托(Delegate) 是存有对某个方法的引用的一种引用类型变量 委托操作顺序 1,定义一个委托类…...

jetcache:阿里这款多级缓存框架一定要掌握

0. 引言 之前我们讲解了本地缓存ehcache组件,在实际应用中,并不是单一的使用本地缓存或者redis,更多是组合使用来满足不同的业务场景,于是如何优雅的组合本地缓存和远程缓存就成了我们要研究的问题,而这一点&#xff…...

干货 | 如何做一个简单的访谈研究?

Hello,大家好! 这里是壹脑云科研圈,我是喵君姐姐~ 心理学中研究中,大家常用的研究方法大多是实验法、问卷调查法等,这些均是定量研究。 其实,作为质性研究中常用的访谈法,可对个体的内心想法进…...

4年外包出来,5次面试全挂....

我的情况 大概介绍一下个人情况,男,毕业于普通二本院校非计算机专业,18年跨专业入行测试,第一份工作在湖南某软件公司,做了接近4年的外包测试工程师,今年年初,感觉自己不能够再这样下去了&…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...

【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案

目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...

手机平板能效生态设计指令EU 2023/1670标准解读

手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...

Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成

一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...