Android 优化之卡顿优化的实现
作者:七适散人 发布时间:2022-03-03 21:34:25
Android 系统每隔 16ms 会发出 VSYNC 信号重绘界面(Activity)。之所以是 16ms,是因为 Android 设定的刷新率是 60FPS(Frame Per Second),也就是每秒 60 帧的刷新率,约合 16ms 刷新一次。
这就意味着,我们需要在 16ms 内完成下一次要刷新的界面的相关运算,以便界面刷新更新。
假设我们更新屏幕的背景图片需要 24ms 来做这次运算,当系统在第一个 16ms 时刷新界面,由于运算还没有结束,无法绘出图片。当系统隔 16ms 再发一次 VSYNC 信息重绘界面时,用户才会看到更新后的图片。也就是说 32ms 后才看到了这次刷新(并不是 24ms),这就是丢帧(dropped frame)。
丢帧给用户的感觉就是卡顿,而且如果运算过于复杂,丢帧会更多,导致界面常常处于停滞状态。
卡顿原因
过于复杂的布局
界面性能取决于 UI 的渲染性能,UI 渲染的整个过程由 CPU 和 GPU 两个部分协同完成。CPU 负责 UI 布局元素的 Measure、Layout、Draw 等相关运算执行,GPU负责栅格化(rasterization),将 UI 元素绘制到屏幕上。
如果 UI 布局层次太深,或是自定义控件的 onDraw 中有复杂运算,CPU 的相关运算就可能大于 16ms,导致卡顿。
过度绘制
UI 线程的复杂运算
UI 线程的复杂运算会造成 UI 无响应,导致 ANR,但更多的是造成 UI 响应停滞卡顿,ANR 是卡顿的极致。
频繁的 GC
优化方法
1、减少刷新次数
比如进度更新,要进度有变化再去刷新,且保证频率不得高于系统的刷新频率。
2、避免非必要的刷新
若控件不可见,则无需刷新。
3、避免后台线程影响
如列表控件,在滑动时不要去加载图片,可以在滑动监听里停止图片的加载。
4、局部刷新
如 RecyclerView 的 DiffUtil。自定义 View 可以使用下面两个方法:
invalidate(Rect dirty);
invalidate(int left, int top, int right, int bottom);
5、尽量使用属性动画,它减少了自身的重绘。最后要清除
StringBuilder,List 等在创建时传入一个合适的参数指定初始容量,以避免频繁扩容的开销。
6、开启硬件加速
7、原理可见 Android硬件加速原理与实现简介,理解Android硬件加速原理的小白文
Application 级别
<application android:hardwareAccelerated="true" />
Activity 级别
<activity android:hardwareAccelerated="true" />
Window 级别
getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
View 级别
// 如果是 software,会将 View 绘制到一个 Bitmap,
// 然后依然是通过硬件加速将 Bitmap 绘制到 Canvas
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
LAYER_TYPE_NONE:普通渲染方式,不会返回一个离屏的缓冲,默认值。
LAYER_TYPE_HARDWARE:如果这个应用使用了硬件加速,这个 View 将会在硬件中渲染为 硬件纹理,如果应用程序并没有被硬件加速,则其效果和 LAYER_TYPE_SOFTWARE 相同。
LAYER_TYPE_SOFTWARE:此 View 通过软件渲染为一个 Bitmap。
检查是否开启了硬件加速
view.isHardware-Accelerated();
Canvas.isHardwareAccelerated();
如果 View 中要处理中文长文本,需要关闭硬件加速。因为每个中文编码不一样,缓存效果不理想。
监控
《Android 应用性能优化最佳实践》2.8 章,主要利用 MainLooper 里的 Printer。
BlockCanary 开源库
StrctMode
ANR
Activity 的 View:5 秒无响应
BroadcastReceiver:10 秒无响应
Service:20 秒无响应
ANR 时,系统会生成一个 traces.txt 的文件放在 /data/anr/ 下。通过 adb 命令将其导出到本地
$adb pull data/anr/traces.txt ~/Desktop
UI 线程做耗时操作,内存泄露导致内存不足都可能产生 ANR。
来源:https://www.jianshu.com/p/5e508beffac8


猜你喜欢
- 本文实例讲述了Java实现的对称加密算法AES定义与用法。分享给大家供大家参考,具体如下:一 简介1、AES是目前使用最多的对称加密算法。2
- 一、简介1.什么是GUID?全局唯一标识符(GUID,Globally Unique Identifier),GUID也称作 UUID(Un
- 在项目开发中某些场景必须要用到启动项目后立即执行方式的功能,如我们需要去初始化数据到redis缓存,或者启动后读取相应的字典配置等,这篇文章
- 一、问题分析及解决方案1、问题分析上一章我们讲过远程仓储统一管理配置信息,客户端可以通过统一配置服务中心 config server 服务端
- 本文实例讲述了Java实现的微信公众号获取微信用户信息。分享给大家供大家参考,具体如下:注: 这里获取用户信息方式和网页授权获取
- 如下所示:TextView tv = (TextView) findViewById(R.id.text); tv.getPaint().s
- 项目需求最近项目中有一个需求就是让Java代码去代替人工操作,自动生成PPT,具体就是查询数据库数据,然后根据模板文件(PPT),将数据库数
- 本文实例讲述了C#采用OpenXml给Word文档添加表格的方法,是非常实用的操作技巧。分享给大家供大家参考。具体分析如下:这里将展示如何使
- 前言若你的工程还没有进行基础配置,请查看我的博文Unity 之 ShaderGraph入门使用详解,按照步骤操作完成配置即可,还能顺便学习一
- Maven本地jar引用的实现方法有的时候需要在maven工程项目中引用本地的jar,pom.xml配置如下:<dependency&
- 本文实例讲述了Android播放多张图片形成的一个动画。分享给大家供大家参考,具体如下:在Android里可以逐帧的播放图片,然后产生一种动
- @Value("${xxx}")取properties时中文乱码(1)检查spring的配置文件中,properties
- 为什么使用logback记得前几年工作的时候,公司使用的日志框架还是log4j,大约从16年中到现在,不管是我参与的别人已经搭建好的项目还是
- 本文实例讲述了Android编程中自定义dialog用法。分享给大家供大家参考,具体如下:dialog是android中提供的一组弹出提示框
- 首先,查到java里文件重命名的方法为:renameTo();我将180张图片放在d:\\backup下,用下面的程序进行重命名:publi
- 使用Mybatis的开发者,大多数都会遇到一个问题,就是要写大量的SQL在xml文件中,除了特殊的业务逻辑SQL之外,还有大量结构类似的增删
- 本文实例为大家分享了java实现滑动验证解锁的具体代码,供大家参考,具体内容如下1.html:<div class="dra
- * 缓存内存缓存本地缓存(SD卡缓存)网络缓存缓存顺序:首先从网络获取图片资源,然后将当前的图片缓存到本地,然后再缓存到内存中,那么下次访问
- 1. * 在 Spring Boot 可以可以在以下情况执行操作:在将请求发送到控制器之前在将响应发送给客户端之前2. * 使用下面实现
- android提供的工具链和开发工具比较完善,因此它的开发环境的搭建比较简单,相信许多朋友都已经搭建好环境,并编写了HelloA