Android 应用冷启动优化

冷启动相关概念

应用启动概念

  • 冷启动:首次打开app或者app彻底销毁后再次打开app(开关机后),这也是我们进行启动速度优化的主要方向。
  • 热启动:应用运行中按home键再打开应用。
  • 温启动:介于两者之间,比如:说用户关闭应用又重新启动应用,这是应用进程还没被销毁。或者系统主动释放掉后台应用,然后用户就将它启动,这时虽然要再重新执行onCreate,但是saveInstanceState实例已经保存,可以提高启动速度。

谷歌官方应用启动时间说明

冷启动时间

冷启动优化就是要缩短冷启动的时间,冷启动时间获取方法,先kill掉进程,或者重新安装一个应用,串口输入下面的命令:

am start -W com.jane.demo/.MainActivity

发送命令后有下面的数据,TotalTime是冷启动的时间。

Status: ok
LaunchState: COLD
Activity: com.jane.demo/.MainActivity
TotalTime: 788
WaitTime: 792

冷启动优化方法

优化前注意应用版本(debug还是release),之前新建一个空项目(只显示一个hello world),想测试想一个空项目启动大概需要多长时间。结果用了接近800ms,震惊不已,后面发现是debug版本的原因,改为release后400ms,降低了一半。

布局加载优化

1、减少布局复杂度

可以使用merge等减少界面层级,这个是比较常用的方法。

2、异步加载

也可以使用异步加载布局的方式AsyncLayoutInflaterAsyncLayoutInflater是谷歌提供的一个异步加载UI方案,其可以异步加载控件并回调给UI,以此减少主线程消耗。对源码和实现原理感兴趣的可以看到后面的参考文章,这里简单看下使用方式:

先在appgradle下加入依赖包。

 implementation 'androidx.asynclayoutinflater:asynclayoutinflater:1.0.0'

如下为测试代码:

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {//测试1:使用原始方式加载//setContentView(R.layout.activity_main);//测试2:使用AsyncLayoutInflater异步加载new AsyncLayoutInflater(this).inflate(R.layout.activity_main,null, new AsyncLayoutInflater.OnInflateFinishedListener(){@Overridepublic void onInflateFinished(View view, int resId, ViewGroup parent) {setContentView(view);         }}); }
}
  • 第一次测试,onCreate中直接调用setContentView(),然后看冷启动时间:TotalTime: 829
  • 第二次测试,使用AsyncLayoutInflater异步加载,冷启动时间:TotalTime: 712

启动耗时操作后移

Android 12 SplashScreen API快速入门在郭神的这个文章中,通过验证得出结论:onCreate()onResume()等生命周期方法都是在App开始绘制第一帧之前执行的,因此在这些生命周期函数中,耗时的操作应该后移或者放到子线程处理。

1、使用View.post()方法后移耗时操作

郭神的文章有分析,post()回调则是在App绘制第一帧之后执行的。因此可以在View.post()方法后,再执行耗时操作。这个方法要比使用Handlerdelay要好,因为delay的时间是不确定的。

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mActivityMainBinding = ActivityMainBinding.inflate(getLayoutInflater());View rootView = mActivityMainBinding.getRoot();setContentView(rootView);//测试1:耗时300ms操作/* try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}*/       rootView.post(new Runnable() {@Overridepublic void run() {//测试2:耗时300ms操作try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}}});            }
}
  • 第一次测试,把300ms耗时操作直接放在onCreate中,然后看冷启动时间:TotalTime: 1124
  • 第二次测试,把300ms耗时操作放在IdleHandler的回调中,冷启动时间:TotalTime: 853

2、使用IdleHandler,后移耗时操作

IdleHandler会在MessageQueue中没有Message要处理或者要处理的Message都是延时任务的时候得到执行,说明此时线程是空闲状态。如果是在主线程,则表明当前UI没有绘制动作,所以可以根据监听IdleHandler是否执行来判断UI是否绘制完成,从而避免在UI绘制的时候进行耗时操作,影响UI绘制效率。

queueIdle()方法回调,说明UI第一帧绘制完成,可以理解为UI首次可见,这个比onResume精确的多,因为onResume回调的时候界面还没有开始绘制,此时界面是不可见的,测试代码如下;

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mActivityMainBinding = ActivityMainBinding.inflate(getLayoutInflater());View rootView = mActivityMainBinding.getRoot();setContentView(rootView);//测试1:耗时300ms操作/* try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}*/Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {@Overridepublic boolean queueIdle() {//此处添加处理任务//测试2:耗时300ms操作try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}// 返回false表示MessageQueue在执行完这段代码后将该IdleHandler删除,反之不删除,下一次继续执行return false;}});}
}
  • 第一次测试,把300ms耗时操作直接放在onCreate中,然后看冷启动时间:TotalTime: 1124
  • 第二次测试,把300ms耗时操作放在IdleHandler的回调中,冷启动时间:TotalTime: 878

3、使用子线程处理耗时操作

在测试用,将模拟的耗时操作放到了子线程中执行,后面又给子线程加上了一个最低的优先级。

在Android中,线程优先级范围从1到10,其中1是最低优先级,10是最高优先级。默认情况下,所有线程都具有相同的优先级5,也就是new一个线程出来优先级就是5。

通过设置线程的优先级,我们可以改变线程在调度器中的竞争情况,从而影响其执行顺序。推荐在Application的某些初始化方法使用子线程加载。

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mActivityMainBinding = ActivityMainBinding.inflate(getLayoutInflater());View rootView = mActivityMainBinding.getRoot();setContentView(rootView);//测试1:耗时300ms操作/* try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}*///测试2:开一个子线程操作Thread thread = new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}}});//测试3:给子线程加一个低的优先级thread.setPriority(Thread.MIN_PRIORITY);thread.start();}
}
  • 第一次测试,把300ms耗时操作直接放在onCreate()中,然后看冷启动时间:TotalTime: 1124
  • 第二次测试,把300ms耗时操作放在子线程中,冷启动时间:TotalTime: 776
  • 第三次测试,给子线程加一个低的优先级,冷启动时间:TotalTime: 730

实际测试中,第二次和第三次时间其实是差不多的,都有大一点有小一点的,这个在我的测试代码中优化不明显。但是还是建议加上,不然也会争抢主线程资源,影响优化启动时间。

码字不易有帮助到大家请点赞、收藏,谢谢。

参考文章:

【Android笔记】异步加载View,AsyncLayoutInflater原理
IdleHandler原理及使用

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

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

相关文章

动手学深度学习-pytorch版本(二):线性神经网络

参考引用 动手学深度学习 1. 线性神经网络 神经网络的整个训练过程,包括: 定义简单的神经网络架构、数据处理、指定损失函数和如何训练模型。经典统计学习技术中的线性回归和 softmax 回归可以视为线性神经网络 1.1 线性回归 回归 (regression) 是能为一个或多个…

Linux系统的目录结构

file system hierarchy standard文件系统层级标准,定义了在类Unix系统中的目录结构和目录内容。 即让用户了解到已安装软件通常放置于哪个目录下。 Linux目录结构的特点 使用树形目录结构来组织和管理文件。 整个系统只有一个根目录(树根)&a…

【SA8295P 源码分析】51 - QNX NFS Server + Android NFS Client 完整配置

【SA8295P 源码分析】51 - QNX NFS Server + Android NFS Client 完整配置 一、QNX 侧 NFS Server 修改:ip 为 192.168.118.21.1 配置拷贝 nfsd、rpcbind 到 /mnt 目录下1.2 配置 exports1.3 为NFS 共享目录挂载镜像1.4 修 startup.sh 开机自启动 nfsd Server1.5 关闭 QNX 防火…

记录几个Hudi Flink使用问题及解决方法

前言 如题,记录几个Hudi Flink使用问题,学习和使用Hudi Flink有一段时间,虽然目前用的还不够深入,但是目前也遇到了几个问题,现在将遇到的这几个问题以及解决方式记录一下 版本 Flink 1.15.4Hudi 0.13.0 流写 流写…

docker redis 配置文件样例

文章目录 1. redis的配置文件1.1 chatGPT 写的配置样例及坑点。 2. docker-compose.yml 文件 1. redis的配置文件 redis官方的配置文件样例 非常有用, 都是从官方文档过摘过来的 1.1 chatGPT 写的配置样例及坑点。 #以下配置来自 chatGPT # 设置 Redis 绑定的 IP…

Flink之时间语义

Flink之时间语义 简介 Flink中时间语义可以说是最重要的一个概念了,这里就说一下关于时间语义的机制,我们下看一下下面的表格,简单了解一下 时间定义processing time处理时间,也就是现实世界的时间,或者说代码执行时,服务器的时间event time事件时间,就是事件数据中所带的时…

DataWhale夏令营第三期-CV赛道-第二次打卡

脑部PET比赛 第二次打卡 运行cnn Baseline时第一段代码报错 FutureWarning: RandomContrast has been deprecated. Please use RandomBrightnessContrast warnings.warn( 根据报错信息新版本的RandomContrast已经弃用,改为RandomBrightnessContrast方法即可。 从这…

nginx代理webSocket链接响应403

一、场景 使用nginx代理webSocket链接,nginx响应403 1、nginx访问日志响应403 [18/Aug/2023:09:56:36 0800] "GET /FS_WEB_ASS/webim_api/socket/message HTTP/1.1" 403 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit…

【数据结构】循环队列

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …

浏览器 - 事件循环机制详解

目录 1,浏览器进程模型进程线程浏览器的进程和线程1,浏览器进程2,网络进程3,渲染进程 2,渲染主线程事件循环异步同步 JS 为什么会阻塞渲染任务优先级 3,常见面试题1,如何理解 js 的异步2&#x…

C语言刷题 1

文章目录 题目答案与解析123 题目 1.strcpy实现 自己设计函数模拟实现库函数strcpy 2.strlen实现 自己设计函数模拟实现库函数strlen 3.调整奇数偶数顺序 输入一个整数数组,实现一个函数,来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部…

❤ Vue工作常用的一些动态数据和方法处理

❤ Vue工作常用的一些动态数据和方法处理 &#xff08;1&#xff09;动态拼接相对路径结尾的svg 错误写法一 ❌ 正确写法 &#x1f646; <img :src"require(/assets//amazon/svg/homemenu${index}.svg)" style"height: 20px;display: block;margin: 0 au…

关于视频监控平台EasyCVR视频汇聚平台建设“明厨亮灶”具体实施方案以及应用

一、方案背景 近几年来&#xff0c;餐饮行业的食品安全、食品卫生等新闻频频发生&#xff0c;比如某火锅店、某网红奶茶&#xff0c;食材以次充好、后厨卫生被爆堪忧&#xff0c;种种问题引起大众关注和热议。这些负面新闻不仅让餐饮门店的品牌口碑暴跌&#xff0c;附带的连锁…

[JavaWeb]【二】Vue Ajax Elemnet Vue路由打包部署

目录 一 什么是Vue 1.1 Vue快速入门 1.2 常用指令 1.2.1 v-bind && v-model 1.2.2 v-on 1.2.3 v-if && v-show 1.2.4 v-for 1.2.5 案例 1.3 生命周期 二 Ajax 2.1 Ajax介绍 2.2 同步与异步 2.3 原生Ajax&#xff08;繁琐&#xff0c;过时了&#xff09…

手机技巧:分享五个非常实用的生活类APP

目录 1、我的桌面iScreen-桌面美化神器 2.Just Rain-创意听雨声APP 3.得言-美文句子神器 4、微手帐 5、暗盒-隐私保护神器 今天给大家整理5个非常实用的实用APP软件&#xff0c;感兴趣的朋友可以下载试试&#xff01; 1、我的桌面iScreen-桌面美化神器 我的桌面iScreen是一…

[uni-app] uview封装Popup组件,处理props及v-model的传值问题

文章目录 需求及效果遇到的问题解决的办法偷懒的写法 需求及效果 uView(1.x版本)中, 有Pop弹出层的组件, 现在有个需求是,进行简单封装,有些通用的设置不想每次都写(比如 :mask-custom-style"{background: rgba(0, 0, 0, 0.7)}"这种) 然后内部内容交给插槽去自己随…

系统架构设计专业技能 · 系统工程与系统性能

系列文章目录 系统架构设计专业技能 网络技术&#xff08;三&#xff09; 系统架构设计专业技能 系统安全分析与设计&#xff08;四&#xff09;【系统架构设计师】 系统架构设计高级技能 软件架构设计&#xff08;一&#xff09;【系统架构设计师】 系统架构设计高级技能 …

手写Promise-then方法的设计

then方法的设计 实现then方法回调执行顺序 实现then方法 then(onFulFilled,onRejected){this.onFulFilled onFulFilled;this.onRejected onRejected;}回调执行顺序 再执行resolve的时候执行then方法回调&#xff0c;会存在一个问题&#xff0c;无法拿到回调方法的&#xff0…

2023年上半年软件设计师下午真题及答案解析

试题一(15分) 随着农业领域科学种植的发展&#xff0c;需要对农业基地及农事进行信息化管理&#xff0c;为租户和农户等人员提供种植相关服务&#xff0c;现欲开发农事管理服务平台&#xff0c;其主要功能是&#xff1a; (1)人员管理&#xff1a;平台管理员管理租户&#xff…

​Redis概述

目录 Redis - 概述 使用场景 如何安装 Window 下安装 Linux 下安装 docker直接进行安装 下载Redis镜像 Redis启动检查常用命令 Redis - 概述 redis是一款高性能的开源NOSQL系列的非关系型数据库,Redis是用C语言开发的一个开源的高键值对(key value)数据库,官方提供测试…