《Android性能优化》学习笔记—启动优化

news2024/12/24 21:03:16

为什么要做App的启动优化?

网页端存在的一个定律叫8秒定律:即指用户访问一个网站时,如果等待打开的时间超过8秒,超过70%的用户将会放弃等待。

同样的,移动端也有一个8秒定律:如果一个App的启动时间超过8秒或有明显的卡顿,80%的用户将会退出应用并对程序员进行口吐芬芳。当然这是我瞎编的,但却不代表是不存在的。最起码肯定会影响App在市场上的评分,进而让更多的用户在对比过程中选择竞品。
知道了启动优化的重要性,那么接下来我们就来分析下如何优化App的启动,本文内容主要分为以下三部分:
在这里插入图片描述分析优化分析优化方向

App应用主要有三种启动状态:冷启动、热启动和温启动。

1、 冷启动:耗时最长,也是主要的优化点;(恋爱前的女人)

冷启动前,系统主要做了三件事:

  • 加载并启动应用。
  • 在启动后立即显示应用的空白启动窗口。
  • 创建应用进程。

创建应用进程后:

  • 创建应用对象。
  • 启动主线程。
  • 创建主 Activity。
  • 扩充视图。
  • 布局屏幕。
  • 执行初始绘制

在这里插入图片描述

2、热启动:耗时最短,将activity从后台带到前台;(热恋中的女人)

3、温启动:耗时较长,重走了Actiivty的生命周期。(结婚后的女人)

从应用的启动状态中,我们可以分析得出,剥除系统本身的任务动作外(这部分我们是无法进行操作修改的),其实我们的启动优化方向主要就是:Application和Activity的生命周期、主视图的布局优化

相关数据测量

优化App的启动速度前,我们得先获取App的一些启动数据,根据这些数据才能准确找到优化的点,才能对优化后的操作做一个准确的评估。(下面的相关代码我将会拿之前的一个旧项目来做演示,一是更贴近实际开发情况,比demo更加直观;二是顺手给优化了,何乐而不为呢?)

1、获取启动时间

adb命令法:adb shell am start -S -W packagename/activity(含包名)

在这里插入图片描述

  • ThisTime:最后一个 Activity 启动时间;
  • TotalTime:所有 Activity 启动耗时(这里只启动了一个 MainActivity);
  • WaitTime:AMS 启动 Activity 的总耗时;

adb 命令虽然简单好用,但还是有不少缺点的:

  • 只能线下使用,而在实际开发过程中,用户的启动时间才是最好的参考指标;
  • 非精确的时间,这里只是显示了 Activity 启动完毕的时间,但对于用户的直观体验来说,只有首页的数据展示出来,才算是真正的启动完成。手动打点法

我们先定义一个LaunchTimer类,用来记录启动时间:

public class LaunchTimer { 
  private static long mTime; 
  //开启时间 
  public static void startTime() { 
    mTime = System.currentTimeMillis(); 
  }
  //结束时间 
  public static void endTime() { 
    LoggerManager.d("启动时间:" + (System.currentTimeMillis() - mTime)); 
  } 
}

在Application类的attachBaseContext()方法中打入开始启动时间点:

protected void attachBaseContext(Context base) { 
  super.attachBaseContext(base); 
  LaunchTimer.startTime(); 
}

在我们的首页第一条数据展示成功后打入结束时间点:(ps:网上很多文章都在 onwindowfocuschanged()方法中打入结束时间,其实这个方法只是首帧时间,并不代表我们的页面数据等全部展示出来了。我们做优化,还是得以用户的实际体验来作为参考价值,不能仅仅KPI化)

//是否已经记录启动时间 
private boolean mIsRecord = false; 
@Override 
protected void convert(BaseViewHolder helper, final HomeListBean.DataBean item) { 
  if (helper.getPosition() == 1 && !mIsRecord) { 
    mIsRecord = true; 
    final View contentView = helper.getView(R.id.home_item_rl); 
    //监听第一条数据的绘制完成时间 
    contentView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 
      @Override 
      public boolean onPreDraw() { 
        contentView.getViewTreeObserver().removeOnPreDrawListener(this); 
        LaunchTimer.endTime(); return true; 
      } 
    }); 
  } 
}

运行我们的代码,可以看到启动时间是3111毫秒,正常来说,是会比用adb命令打出的时间要长点。
在这里插入图片描述
手动打点的好处:

  • 可以线上使用,统计真实用户的启动时间
  • 时间准确,结合用户真实体验,参考价值更高

2、其他优化分析工具

我经常使用的启动优化工具主要有Traceview(官方文档)和systrace(官方文档),Traceview虽然比较全面,但性能消耗太大,这里不做过多介绍,有兴趣的朋友可以自行查看官方文档,这里主要介绍 systrace这个工具(使用前需得先安装python)。

先打点:

public void onCreate() { 
  super.onCreate(); 
  //使用兼容的TraceCompat打入开始点 
  TraceCompat.beginSection("AppBegin"); 
  if (instance == null) { 
    instance = this; 
  }
  if (IS_DEBUG_ABLE) { 
    initLogger(); 
  }
  initBugly(); 
  Tiny.getInstance().init(this);
  //初始化tiny图片压缩工具 
  initJPush(); 
  initSkin(); 
  RichText.initCacheDir(this);
  //设置缓存 
  initFragmentation();
  MMKV.initialize(this); 
  TraceCompat.endSection(); 
  //使用兼容的TraceCompat记录结束点 
  TraceCompat.endSection(); 
}

安装App,使用systrace命令:python systrace.py -b 32768 -t 10 -a packagename -o outputfile.html sched gfx view wm am app (命令执行过程中点击启动App)

运行操作后,打开我们的html文件,可以看到我们app的启动相关数据:
在这里插入图片描述
运行操作后,打开我们的html文件,可以看到我们app的启动相关数据:
在这里插入图片描述
图中红圈部分是我们需要注意的地方,AppBegin就是我们打点的代表区间,可以看到这段区间时间是 732.127毫秒。最下面有两个数值,一个是WallDuration,这个就是我们代码的执行时间,另一个 CPUDuration是我们的CPU执行时间。

如需完整版 Android性能优化学习笔记 请点击免费获取

优化技巧

终于讲到我们的优化技巧了,具体优化我们可以分为以下几种方式:

  • 闪屏优化
  • 业务优化
  • 线程优化
  • UI优化

在这里插入图片描述

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

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

相关文章

UNIAPP实战项目笔记66 当前用户更改购物车商品数量的前端和后端交互

UNIAPP实战项目笔记66 当前用户更改购物车商品数量的前端和后端交互 思路 前端改变数量的时候将数据发送到后端 后端接收到数据后更改数据库中的数据 案例截图 代码 前端代码 cart.js export default{state:{list:[/* {id:1,name:"332经济法能聚聚会技能大赛 经济法能聚…

vmware15+ubuntu+AS

一、VMware Workstation 与 Device/Credential Guard 不兼容 安装VMware15后,在运行启动ubuntu时一直提示与Device/Credential Guard不兼容 1、WINR打开运行,输入services.msc; 2、服务中找 HV主机服务,双击打开设置改为禁用&am…

【Python入门篇】——Python中判断语句(if elif else语句,判断语句的嵌套与实战案例)

作者简介: 辭七七,目前大一,正在学习C/C,Java,Python等 作者主页: 七七的个人主页 文章收录专栏: Python入门,本专栏主要内容为Python的基础语法,Python中的选择循环语句…

Day3--C高级3

一.编写一个名为myfirstshell.sh的脚本,它包括以下内容。 1、包含一段注释,列出您的姓名、脚本的名称和编写这个脚本的目的 2、和当前用户说“hello 用户名” 3、显示您的机器名 hostname 4、显示上一级目录中的所有文件的列表 5、显示变量PATH和HO…

【云原生】Kubernetes二进制--多节点Master集群高可用

多节点Master集群高可用 一、Kubernetes多Master集群高可用方案1、实现高可用方法2、多节点Master高可用的部署 二、多节点Master部署1、配置master022、修改配置文件kube-apiserver中的IP3、在 master02 节点上启动各服务并设置开机自启 三、负载均衡部署1、配置nginx的官方在…

Google I/O 2023 大会上发布了一些令人兴奋的技术和产品,让我们一起来看看吧!

文章目录 Google I/O 2023 的主要内容- **Android 14**:- **Google Pixel 7**:- **Google Assistant**:- **Google Lens**:- **Google Cloud**: Google I/O 2023 大会四大主题 回顾:跨移动、网络、AI 和云A…

以太坊钱包私钥爆破产业链和攻击案例

一:产业链频道:小飞机搜索"BRUTE_FORCE_CRYPTO_WALLET" 2、github项目(有成熟的工具)GitHub - Houzich/CUDA-GPU-Brute-Force-Mnemonic-Old-Electrum-V1: CUDA-GPU-Brute-Force-Mnemonic-Old-Electrum-V1 3、揭秘以太坊 Vanity 生成器 Profanity 私钥破解…

C++学习路线-自用

C学习路线 做目录索引用,后续更新 初步想在学习完成后做对应的link 1、summary 参考网址 https://mp.weixin.qq.com/s/tXilzUzN7cDhnc3ztw4Vlw https://blog.csdn.net/qq_43564374/article/details/109409256 https://zhuanlan.zhihu.com/p/130364187 学习方式 看书…

景区剧本杀开发方案

景区剧本杀软件发展趋势包括以下几个方面: 个性化定制:随着用户需求的不断增加,景区剧本杀软件将更加注重个性化定制,满足不同用户的需求。 跨平台支持:景区剧本杀软件将逐渐实现跨平台支持,比如在…

经典命令--sort、uniq、tr、cut等

目录 一:sort--排列工具 1.sort命令介绍 2.sort命令常用选项 3.sort命令事例 二: uniq--去重工具 1.uniq命令介绍 2.uniq命令常用选项 3.uniq命令事例 4.筛选出重复3次的ip 5.将超过3次登录失败的用户加入黑名单 三:tr-- 替换工具 1.tr命令介绍…

10个前端开发者务必知道的JavaScript 技巧

前言 过去,我写了很多垃圾代码,现在看起来很糟糕。 当我再次看到那些代码片段时,我甚至怀疑自己是否适合做程序员。 所以,这里有 10 个我总结的JavaScript 技巧,可以帮助你避免编写我曾经做过的那种垃圾代码。 Prom…

提取每个汉字的首字母

1&#xff1a;在项目 POM 中 引入 汉字拼音转换JAR包 ​​​​​<dependency> <groupId>com.belerweb</groupId> <artifactId>pinyin4j</artifactId> <version>2.5.1</version> </dependency> 2:工具类 public…

Vue项目修改页面标签

Vue项目修改页面标签 1、在 Vue CLI 创建的项目中&#xff0c;可以通过修改 public/index.html 文件来改变网页标题。 2、在 Element UI 中&#xff0c;可以通过修改 document.title 属性来改变页面的标题。以下是一个示例代码&#xff1a; export default {mounted() {// 修改…

Android 检查网络状态和监听网络状态变化

此篇存在的主要意义在于解决用户使用app中网络状态发生了变化&#xff0c;需要我们去动态监听网络连接状态&#xff08;有网、无网&#xff09;、网络类型 &#xff08;包括wifi、移动网络 -> 3G、4G等等&#xff09; 文章目录 门前授课具体实现异常场景兴趣扩展 门前授课 …

设备产线运维合集丨图扑数字孪生流水线,提升产品装配自动化效率

前言 图扑软件基于 HTML5&#xff08;Canvas/WebGL/WebVR&#xff09;标准的 Web 技术&#xff0c;满足了工业物联网跨平台云端化部署实施的需求&#xff0c;以低代码的形式自由构建三维数字孪生、大屏可视化、工业组态等等。从 SDK 组件库&#xff0c;到 2D 和 3D 编辑&#…

类加载器和双亲委派模型

类加载机制的第一步就是“加载”&#xff0c;即将Class文件获取二进制字节流并加载到方法区中 这个“加载”动作是放在JVM 之外去实现的&#xff0c;能够让应用程序来决定如何获取所需要的类 类和类加载器 对于任意一个类&#xff0c;都必须由加载它的类加载器和这个类本身一…

数字藏品的价值和意义

2022年以来&#xff0c;数字藏品概念在国内火热起来。从年初的《关于防范 NFT相关金融风险的倡议》到8月份央行数字货币 DCEP的正式面世&#xff0c;从中国香港首个“NFT”艺术品在香港拍卖市场成交到国内多家互联网大厂推出数字藏品平台&#xff0c;越来越多的企业开始试水数字…

Spring Cloud Alibaba--Nacos服务注册和配置中心

文章目录 一、什么是Nacos1.1、Nacos的由来1.2、Nacos的特性1.3、Nacos的下载和启动 二、Nacos服务注册2.1、代码示例2.2、各种注册中心的比较CAP定理多个注册中心比较 三、Nacos配置中心3.1、Nacos配置管理3.2、代码示例3.3、多环境多项目管理3.3.1、命名空间3.3.2、Group分组…

递归到动态规划:空间压缩技巧-纸币问题的有限张数

这个题是我们纸币问题的第三题 题目大意&#xff1a; arr是货币数组&#xff0c;其中的值都是正数。再给定一个正数aim。 每个值都认为是一张货币&#xff0c; 认为值相同的货币没有任何不同&#xff0c; 返回组成aim的方法数 例如&#xff1a;arr {1,2,1,1,2,1,2}&#xff0…

【C】模拟实现atoi,atof函数

目录 atoi函数 atof函数 模拟实现atoi&#xff0c;atof函数 1、atoi模拟实现 2、atof模拟实现 3、测试案例代码 atoi函数 atoi函数是将字符串转换成整数 函数头文件&#xff1a;#include <stdlib.h> 函数原型&#xff1a;int atoi(const char *str); 参数&…