Android---启动速度优化

news2024/11/19 3:29:14

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 {
    @Override
    public 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 简化布局

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

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

相关文章

KDGK-F断路器机械特性测试仪

一、产品概述 KDGK-F 断路器机械特性测试仪可用于各电压等级的真空、六氟化硫、少油、多油等电力系统高压开关的机械特性参数测试与测量。测量数据稳定,抗干扰性强,可在500KV等级及以下电站做实验,接线方便,操作简单,是…

TikTok选品要怎样才能选到爆品?!

对于做TikTok的商家而言,选品是非常重要的,因为一个产品爆了之后能带动其他产品的销量,那我们要如何有效的选品呢? 一、多平台选品逻辑 首先要知道一个点,在独立站爆的品也会在亚马逊爆,而TikTok已经成为一…

安卓Glide那些事情面试,一篇全部搞定

安卓Glide那些事情面试,一篇全部搞定 一.Glide有几级缓存???二.Gllide源码分析三.内存缓存和磁盘缓存LruCache算法四.Gllide基本使用五.Gllide高级使用:配置1.配置内存和磁盘缓存大小2.配置okhttp3.配置https认证4.使用 一.Glide有…

冲浪杂记——

华为od是指什么? 华为OD(Open Developer Platform)是华为面向全球开发者推出的开放平台,旨在为开发者提供丰富的技术资源和开发工具,支持开发者快速构建基于华为技术的应用程序、解决方案和服务。华为OD平台为开发者提…

微软新Bing全面开放BingChat,无需排队,直接用

我是卢松松,点点上面的头像,欢迎关注我哦! 好消息,所有人都能上手微软Bing了!微软表示,为了感谢大量用户的使用与反馈,从今天起新 Bing 不再有候补名单,只要使用微软账户登录 Bing,…

函数(1)

文章目录 目录1. 函数是什么2. 库函数3. 自定义函数4. 函数的参数4.1 实际参数(实参)4.2 形式参数(形参) 5. 函数的调用5.1 传值调用5.2 传址调用5.3 练习 附: 目录 函数是什么库函数自定义函数函数的参数函数的调用函…

实现北大官网首页的动态图标

逛网站的时候,看见有人在问如何实现北大官网的动态图标,因为做过类似的东西,所以想把这个方法整理下来。 点上去会有一个小动画的那种。 如何实现该图标的动态效果 一句话:用svg实现图标,利用stroke-dasharray和str…

Rust - 切片Slice

Slice类型 Slice数据类型没有所有权,slice允许我们引用集合中一段连续的元素序列而不用引用整个集合。字符串slice(string slice) 是String中 一部分值的引用。如下述代码示例,不是对整个String的引用而是对部分String的引用: fn main() {l…

虹科方案 | HK-Edgility面向未来的安全 SD-WAN

通过上期的文章,我们了解到虹科HK-Edgility软件系统《随时随地保护您的远程工作解决方案》的解决方案。这篇文章,我们将带您了解虹科系统在SD-WAN的方案简介。 一、时代背景 过去,企业使用专线或MPLS解决方案将其站点和办公室连接到企业数据中…

数据结构——链表(python版)

一、链表简介 链表是一种在存储单元上非连续、非顺序的存储结构。数据元素的逻辑顺序是通过链表中的指针链接次序实现。链表是由一系列的结点组成,结点可以在运行时动态生成。每个结点包含两部分:数据域与指针域。数据域存储数据元素,指针域…

封装server类,创建多个server服务

(一)封装server类 MessageHeader.hpp #ifndef _MessageHeader_hpp_ #define _MessageHeader_hpp_ #endif #pragma once enum CMD {CMD_LOGIN,CMD_LOGIN_RESULT,CMD_LOGOUT,CMD_LOGOUT_RESULT,CMD_NEW_USER_JOIN,CMD_ERROR };struct DataHeader {short …

安装RedisBloom插件

前言 安装RedisBloom模块会遇到很多坑,希望你不要和我一样踩的这么全😏。 下载RedisBloom插件 布隆过滤器插件下载地址 github.com/RedisBloom/RedisBloom/releases 在对应的Linux机器下载 wget https://github.com/RedisBloom/RedisBloom/archive/…

一文搞懂,这几种 API 的不同应用场景

API,即应用程序编程接口,为不同应用程序之间的数据和功能交互提供标准化的方法。在现代软件架构中,各种类型的 API 成为了构建了复杂应用系统的关键部分。而随着技术的发展,越来越多的 API 类型也出现了,例如&#xff…

Flash Jetson Linux 刷写系统报错处理

目录 报错一:No such file or directory: dtc解决方案 报错二:ERROR sshpass not found 等其他执行刷写的依赖包解决方案 结论 报错一:No such file or directory: ‘dtc’ 在使用 SDK Manager 刷写Jetson Linux 时,在完成了 Cre…

DD驱动鼠标键盘(驱动级别机器人使用鼠标键盘)

官网下载 DD虚拟键盘虚拟鼠标 github下载 GitHub - ddxoft/master 点击下载后,将驱动包下,这里以win7为例 setup运行安装 安装成功后 可以打开电脑管理,可以看见DD虚拟鼠标和键盘 这里以JAVA接入为例 使用管理员权限启动eclipse &#…

python安装报错error: pybind11 2.10+ requires MSVC 2017 or newer

python安装报错error: pybind11 2.10 requires MSVC 2017 or newer文章来源:https://www.cnblogs.com/viete/p/16909793.html 下载Build Tools for Visual Studio 2017 ,打开后选单个组件,再选VC2017最新版本。 https://download.visualstu…

第7章:字符串函数

字符串函数 1.字符串函数 2.举例 select ASCII(A),CHAR_LENGTH(hello),CHAR_LENGTH(我们), LENGTH(hello),LENGTH(我们) from dual;3.举例 ①select CONCAT(emp.last_name,-worked for-,mgr.last_name) "details" from employees emp left join employees mgr on em…

61.网页设计规则#7_元素之间的空白

为什么需要空白? 适度的空白使设计看起来整洁、现代和精致。空白传达不同片段信息之间的关系。空白意味着布局元素之间存在看不见的关系。 如何去使用空白? 各部分之间使用大量的空白; 元素组之间使用大量的空白。 在各个元素之间使用空白…

优化了成本和安装难度后,UWB信标能否取代蓝牙信标?

1 我们做安U3号是要解决什么问题? (1)信标式设计,解决传统UWB基站安装过程繁琐复杂的问题 传统UWB基站在安装过程中遇上的难题: l 安装位置选取问题:UWB基站的准确度与其安装位置有很大关系,…

qt实现国际化方法与步骤

1. 在程序中所有需要翻译的字符串都用tr封装,如tr("hello"); 2. 在项目文件(.pro)中增加语言翻译文件选项, 如 TRANSLATIONS trans_cn.ts trans_en.ts 3. 在Qt Creator的菜单栏中依次选择“工具”-> ”外部“->“语言家”->&q…