Android 性能优化(六):启动优化的详细流程

news2024/11/17 23:57:28


书接上文,Android 性能优化(一):闪退、卡顿、耗电、APK

从用户体验角度有四个性能优化方向:

  1. 追求稳定,防止崩溃
  2. 追求流畅,防止卡顿
  3. 追求续航,防止耗损
  4. 追求精简,防止臃肿

防止卡顿

卡顿的场景通常与用户交互体验最直接,分别为UI、启动、跳转、响应四个方面,如下图所示。

 主要有两大因素:

  • 界面绘制:层级深、元素复杂、频繁刷新等。由于这些原因导致卡顿的场景更多出现在启动后的初始界面以及跳转到页面的绘制上。
  • 数据处理:数据处理量太大。一般分为三种情况,一是数据在处理 UI 线程,二是数据处理占用 CPU 高,导致主线程拿不到时间片,三是内存增加导致 GC 频繁,从而引起卡顿。


UI优化

主要是绘制和刷新的卡顿,典型表现在页面的列表的滑动加载和刷新。

针对绘制可以使用懒加载,针对刷新可以使用局部刷新。详情参考:

(四)RecycleView 滑动到置顶、Adapter局部刷新

(七)RecycleView 性能提升、卡顿优化


启动优化

启动速度是用户第一印象,过长会让用户失去耐心; 根据行业数据统计,启动速度与用户留存有着直接相关;

对于开发者来说,通过各种技术手段来提升启动性能缩减启动时长,对整站业务的各项指标提升都会有较大帮助。因此,启动优化是各个客户端团队在体验优化方向上十分重要的一环。

评估量化

在计划优化立项之前,先确定两件事。

一、目标任务的启动是否值得优化?

衡量一个任务是否要启动有两个关键指标:“投入产出比”、“产出风险比”

  • 投入产出比:当完成优化任务需要 3人/天,收获90分位 100ms 的优化产出;另一个只收获90分位 10ms 的优化产出。显而易见选前者。因为优化的前期追求的的是优化收益,等到后续开启二期任务、三期任务需要做到更加极致时,才会考虑成本高但收益低的任务。
  • 产出风险比:当做优化任务时,可能会有风险点影响某个业务,这时需要衡量风险影响范围的大小,然后和业务方商讨劣化和优化的抉择,最后敲定任务排期。
二、优化的预期结果是否可量化?

有个比较简单的方法就是对标,比如,竞品App或主流App。

当然,启动优化最终目标是“秒开”,即需要 1s 内完成用户的启动流程。


量化建设

工作的价值体现就在于建设丰富的数据大盘来明确以什么形式、从什么角度、监控什么指标。

启动优化的整体监控可以为:

  • 秒开率、2秒开率、3秒开率...
  • 90分位总体性能、90分位各阶段性能;(波动较小,不会被极端的case影响曲线)
  • 分版本各阶段各项指标、整体各阶段各项指标、主版本各阶段各项指标
  • 分场景,如有无广告等等
  • ...

耗时定义

业内常见的app启动过程阶段一般分为「启动阶段」和「首刷阶段」。

  • 启动阶段:指用户点击icon到见到app的首页,起点为ApplicationonCreate,终点ActivityonWindowFocusChanged()
  • 首刷阶段:指用户见到app的首页到首页列表内容展现起点为ActivityonCreate,终点列表的onAttachedToWindow() 。

为了确保启动优化量化指标的数据能稳定和完整。因此,排除其他启动场景的统计:

  • 启动过程中App退后台
  • 用户未登录场景
  • 特殊场景下的开屏广告,比如有复杂的联动动效
  • 站外push、deeplink拉起。

检测工具

Android Studio 自带的Profiler工具。

如果是 Android 10 及以上就用 Perfetto。


启动阶段

在App的启动流程中,有非常多的启动任务全部在Application的onCreate里被执行,有主线程的有非主线程的,但是不可避免的是,二者都会对启动的性能带来损耗。所以我们需要做的第一件重要的事情就是“启动任务重排与删减

可以把启动任务按优先级分类:

  • 刚需高优任务:这类任务初始化,根本无法进入后续流程。所以,不可延迟,必须第一时间最高优先级执行。比如网络库、路由库、存储库等基础库的初始化。
  • 非刚需高优任务:这类任务不初始化,不影响后续首页UI刷新,比如拉取ab实验配置、ip直连、push推送通知服务、长链接等基础建设项。
  • 非刚需低优任务:这类任务对启动阶段后续流程无决定性影响,可以放在启动阶段结束之后再执行或懒加载。比如 x5内核、在线客服sdk、在线反馈SDK、登陆相关极验/深知SDK、LBS定位、搜索记录、城市json数据解析、Flutter/RN/Weex引擎初始化等。

可以考虑封装一个任务管理器,大致代码参考如下:

TaskManager.getInstance().beginWith(A)
                .then(B)
                .then(C, D)
                .then(E)
                .enqueue();
TaskManager.getInstance().runAfterStartup({ xxx; })

通过任务的大致非精细化的排布,我们不仅仅可以对启动任务能够很好的进行监控,还可以更加容易的找出不合理项。

首刷阶段

从业务的角度出发,找到对启动流程影响最大的业务为切入点,尝试寻求更优的解法。

根据业务流程进行如下考虑:

  • IO 请求优先级提高,例如开屏广告接口请求提前发起。
  • IO wait期间,优化各项初始化,减少大量数据处理导致主线程拿不到时间片CPUTime。
  • 首页UI复杂度简化,列表的第一屏数据尽量走缓存。
1、 SplashActivity与MainActivity合并

当App启动时,会先进入SplashActivity等广告接口返回展示广告,然后转进MainActivity。这个流程对性影响最大的点是:等广告接口时,无法对后续业务做预加载,业务都在MainActivity。另外,启动阶段需要连续启动两个Activity,至少带来 百毫秒 级别的劣化。

合并前后,流程图如下: 

广告原先是以Activity的形式在展现,现在被抽离成 View 的形式去承载逻辑,在 onCreate 中,广告View添加进 DecorView中,完成对首页布局的遮罩。在广告View展示logo图时,底下首页框架是可以进行预加载和渲染。 

补充注意事项: 

MainActivity 作为launchAtivity的单实例问题。App从后台进前台,其他二级页面跳转到首页的依然走生命周期的现象。MainAcitvity 的 launchmode 需要设置为 singleTop。 

首页弹窗管理器需要延迟初始化。在广告View覆盖在上面时,先暂停弹层管理器的生命周期,避免出现其他内容盖住广告。

2、多Tab延迟加载+懒加载

一般MainActivity中的Tab会以fragment形式被提起预加载。而首刷阶段的终点是在首页列表View的onAttachedToWindow()生命期中。

因此,可以考虑其他Tab进行延迟加载和懒加载。即用户不迫切切换Tab,就在首页View绘制时进行预加载;否则就在用户点击Tab切换事件中进行加载(可能卡顿劣化,需风险评估)。

3、布局优化

比如,广告View可以在接口返回数据且经过素材校验后,再进行布局的加载。类似的Banana位、搜索框、其他图片广告等。

  • 布局复用,使用<include>标签重用layout;
  • 提高显示速度,使用<ViewStub>延迟View加载;
  • 减少层级,使用<merge>标签替换父级布局;
  • 其他:使用wrap_content会增加measure计算成本;kotlin by lazy,动态内容加载的场景等。

4、绘制优化

过度绘制是指在屏幕上的某个像素在同一帧的时间内被绘制了多次。

在多层次重叠的 UI 结构中,如果不可见的 UI 也在做绘制的操作,就会导致某些像素区域被绘制了多次,从而浪费了多余的 CPU 以及 GPU 资源。

  • 移除 XML 中非必须的背景,移除 Window 默认的背景、按需显示占位背景图片;
  • 使用 canvas.clipRect() 识别可见区域,只在这个区域内才会被绘制。

可以通过LayoutInspector和Android的调试工具去各自分析了,如果打开LayoutInspector肉眼可见都是红色,赶紧改。

5、page cache

给首页的数据流增加页面级别缓存,让首页首刷不依赖接口返回就可以展示。

以上启动优化的点可以更详细的、更极致的优化,需要根据各自APP情况而定。


阶段成果

优化结果:

  • 从2.87 降至最低时2.1,降幅26.8%
  • 再进行优化后效果不明显,遇到瓶颈 

优化瓶颈

瓶颈是什么?——APP加壳

  • APP加固中的加壳,严重拖慢了APP启动性能;
  • 且爱加密对加壳后的性能损耗无法优化;

如何突破瓶颈?——混淆+VMP

  • 壳的作用:对APPDex文件进行加密,防止APP被反编译,导致源代码泄露;
  • 替代方案: 对代码进行混淆,这也是行业通用做法 VMP加密,一种虚拟机加密技术,加密后将原有代码片段替换成新的片段,在执行时再解密;
  • 去壳需得到安全部门认可: 通过三方机构对加壳、仅混淆、混淆+VMP加密包进行安全测试; 得出结论为安全性 混淆+VMP > 仅混淆 > 仅加壳  

防劣化同样重要

在线上优化工作开展完成且取得了相应成果后,绝对不能放松警惕。

优化一次获得的效果并不是最重要的,最重要的是要有持续的、稳定的优化效果

对于线上用户来说,其实可能并不关心这个版本或者这几个版本是不是变快了,大家可能更需要的是长时间的良好体验。

对于我们这些开发者来说,长时间的良好体验可能才能改变大家对自家 App 的性能印象,让大家认可自家 App 的启动性能,这也是我们优化的初衷。

因此,防劣化和优化同样重要。

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

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

相关文章

【MySQL】5.2MySQL高级语句与sql语句

模板 test、class、class0 mysql> select * from test; -------------------------------- | idcard | name | age | hobbid | -------------------------------- | 01 | lizi | 18 | guangjie | | 02 | monor | 22 | zhaijia | | 03 | sansan | …

FFMPEG C++封装(一)(C++ FFMPEG)

1 概述 FFMPEG是一个C语言开源视音频编解码库。本文将FFMPG4.1.3进行C封装&#xff0c;形成C FFMPG库。 2 架构 架构图如下所示&#xff1a; 架构说明: Init 初始化FFMPEG库。IStream 输入流&#xff0c;FFMPEG的输入音视频文件。Packet 音视频数据包Decoder 音视频编码器F…

electron打包桌面版.exe之vue项目踩坑(vue3+electron 解决打包后首页打开空白,打包后路由不跳转及请求不到后端数据等问题)

vue项目https://www.qingplus.cn/components-web/index打包桌面版问题集合 一、静态资源加载问题 npm run electron_dev桌面版运行后页面空白&#xff0c;内容未加载。 填坑&#xff1a; 打包配置要用相对路径 vite.config.ts文件中的base要改成./&#xff0c;之前加了项目…

Towhee 小记

文章目录 关于 Towhee✨ 项目特点&#x1f393; 快速入门流水线预定义流水线自定义流水线 &#x1f680; 核心概念 关于 Towhee Towhee 是一个开源的 embedding 框架&#xff0c;包含丰富的数据处理算法与神经网络模型。通过 Towhee&#xff0c;能够轻松地处理非结构化数据&am…

【QT】:基本框架

基本框架 一.创建程序二.初识函数1.main2.Widget.h3.Wight.cpp4.Wight.ui5.文件名.pro 三.生成的中间文件 本系列的Qt均使用Qt Creator进行程序编写。 一.创建程序 二.初识函数 1.main 2.Widget.h 3.Wight.cpp 4.Wight.ui 此时再点击编辑&#xff0c;就看到了ui文件的本体了。…

pt-archiver的实践分享,及为何要用 ob-archiver 归档数据的探讨

作者简介&#xff1a;肖杨&#xff0c;软件开发工程师 在数据密集型业务场景中&#xff0c;数据管理策略是否有效至关重要&#xff0c;它直接关系到系统性能与存储效率的提升。数据归档作为该策略的关键环节&#xff0c;不仅有助于优化数据库性能&#xff0c;还能有效降低存储成…

Android-Handler详解_使用篇

本文我将从Handler是什么、有什么、怎们用、啥原理&#xff0c;四个方面去分析。才疏学浅&#xff0c;如有错误&#xff0c;欢迎指正&#xff0c;多谢。 1.是什么 因为Android系统不允许在子线程访问UI组件&#xff0c;否则就会抛出异常。所以咱们平实用的最多的可能是在子线…

「媒体宣传」如何针对不同行业制定媒体邀约方案

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 针对不同行业制定媒体邀约方案时&#xff0c;需要考虑行业特点、目标受众、媒体偏好以及市场趋势等因素。 一、懂行业 先弄清楚你的行业是啥样&#xff0c;有啥特别之处。 了解行业的热…

【地图构建(1)】占用栅格地图构建Occupancy grid mapping

本文主要参考Probabilistic Robotics《概率机器人》一书。 其他参考&#xff1a; 弗莱堡大学课件 博客 含代码博客 0.引言 位姿已知的地图构建(mapping with known poses)的定义&#xff1a;已知机器人的位姿 x 1 : t x_{1:t} x1:t​和传感器的观测数据 z 1 : t z_{1:t} z1:t…

绝地求生:报告长官!速去领取PUBG7周年礼包及7周年活动攻略【附方法】

奖励都需要长官们绑定全球账号&#xff0c;在游戏个人资料处查看是否有绑定&#xff01; PUBG七周年礼包详情&#xff1a; 包含7周年快乐甜筒帽 7周年快乐背包&#xff08;3级&#xff09; 戴墨镜的幽灵 黑货票券 x30 档案管理员宝箱 x1 钥匙 x1 绑定ID登录&#xff0c;或…

【FIneBI可视化工具的使用】

前言&#xff1a; &#x1f49e;&#x1f49e;大家好&#xff0c;书生♡&#xff0c;今天主要和大家分享一下可视化的工具FineBI的详细使用,希望对大家有所帮助。感谢大家关注点赞。 &#x1f49e;&#x1f49e;前路漫漫&#xff0c;希望大家坚持下去&#xff0c;不忘初心&…

大型驱动水冷负载电阻、缓冲器、滤波器和快速放电电阻

EAK业界首创双面水冷负载电阻器&#xff0c;独特的设计&#xff0c;用户更方便的串联并联使用&#xff0c;强大的水流带走更多因充放电带来的热量。AlN高可靠性氮化铝基板保证了热膨胀不会影响电阻的工作。 液冷电阻器使用水或离子水作为冷却剂。通过添加乙二醇&#xff0c;可以…

单调栈(C++)

单调栈,即栈中元素是单调递增的或是单调递减的,是一个比较好用的数据结构. 柱状图中最大的矩形 84. 柱状图中最大的矩形 - 力扣&#xff08;LeetCode&#xff09; 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。…

【SAP2000】在框架结构中应用分布式面板荷载Applying Distributed Panel Loads to Frame Structures

在框架结构中应用分布式面板荷载 Applying Distributed Panel Loads to Frame Structures 使用"Uniform to Frame"选项,可以简单地将荷载用于更多样化的情况。 With the “Uniform to Frame” option, loads can be easily used for a greater diversity of situat…

【书生·浦语大模型实战营第二期】学习笔记1

1. Introduction 开源llm举例&#xff1a;LLaMA 、Qwen 、Mistral 和Deepseek 大型语言模型的发展包括预训练、监督微调&#xff08;SFT&#xff09;和基于人类反馈的强化学习&#xff08;RLHF&#xff09;等主要阶段 InternLM2的显著特点 采用分组查询注意力&#xff08;GQA…

蓝桥杯基础练习汇总详细解析(三)——字母图形、01字符串、闰年判断(详细解题思路、代码实现、Python)

试题 基础练习 字母图形 提交此题 评测记录 资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 利用字母可以组成一些美丽的图形&#xff0c;下面给出了一个例子&#…

web开发发展历程-前端、后端、消息队列、后端架构演进

文章目录 摘要主要内容不同的时代对应不同的技术前端技术的中间阶段-单页面应用前后端分离后端技术演化-云计算平台总体趋势反应式编程 消息队列发展史kafka&#xff0c;rocketmq&#xff0c;pulsar网易后端架构演进架构瓶颈数据库瓶颈服务器瓶颈数据库缓存瓶颈-缓存击穿、雪崩…

Spring Boot:Web开发之三大组件的整合

Spring Boot 前言Spring Boot 整合 ServletSpring Boot 整合 FilterSpring Boot 整合 Listener 前言 在 Web 开发中&#xff0c;Servlet 、Filter 和 Listener 是 Java Web 应用中的三大组件。Servlet 是 Java 代码&#xff0c;通过 Java 的 API 动态的向客户端输出内容。Filt…

7.3*3卷积核生成

1.卷积核 在数字图像处理中的各种边沿检测、滤波、腐蚀膨胀等操作都离不开卷积核的生成。下面介绍如何生成各种3X3的卷积核。为后面的数字图像操作打下基础。   由于图像经过卷积操作后会减少两行两列&#xff0c;因此在生成卷积核的时候一般会对图像进行填充&#xff0c;填充…

day 36 贪心算法 part05● 435. 无重叠区间 ● 763.划分字母区间 ● 56. 合并区间

一遍过。首先把区间按左端点排序&#xff0c;然后右端点有两种情况。 假设是a区间&#xff0c;b区间。。。这样排列的顺序&#xff0c;那么 假设a[1]>b[0],如果a[1]>b[1]&#xff0c;就应该以b[1]为准&#xff0c;否则以a[1]为准。 class Solution { public:static bo…