(三)UI 绘制优化的思路以及解决方案

子曰:温故而知新,可以为师矣。 《论语》-- 孔子


作为性能优化专栏的第三篇,我们就来说一说 UI 绘制优化的思路以及一些解决方案。

1. CPU 与 GPU

CPU
  • 中央处理器。CPU 的任务繁多,做逻辑计算外,还要做内存管理、显示操作,因此 在实际运算的时候性能会大打折扣,在没有 GPU 的时代,不能显示复杂的图形,其运算速度远跟不上今天复杂三维游戏的要求。即使 CPU 的工作频率超过 2GHz 或更高,对它绘制图形提高也不大。这时 GPU 的设计就出来了。
GPU
  • 为了提高图形显示效率以及复杂的图形,设计出了 GPU。主要是为了帮助 CPU 分担图形显示。下面显示一张 GPU 的图:

CPU、GPU

  1. 黄色的 Control 为控制器,用于协调控制整个 CPU 的运行,包括取出指令、控制其他模块的运行等。

  2. 绿色的 ALU ( Arithmetic Logic Unit )是算术逻辑单元,用于进行数学、逻辑运算。

  3. 橙色的 Cache 和 DRAM 分别为缓存和 RAM ,用于存储信息。

从结构图可以看出, CPU 的控制器较为复杂,而 ALU 数量较少。因此 CPU 擅长各种复杂的逻辑运算,但不擅长数学尤其是浮点运算。 我们页面是一个个像素点,以16进制展示,假如某个背景要从白色到红色,明显就是进制之间的转化,那么 ALU 显然擅长这个,所以在 GPU 中 ALU 数量较多的原因。


2. xml 显示过程

Android 开发的 xml 布局是如何显示到页面上? 下面这一张图说明了整个流程:
xml布局显示到界面过程

好了,现在大家应该对 UI 布局渲染流程与绘制有了一个基本的了解。那么我们需要优化什么?想要优化,肯定是有了问题,才会想着优化,那么 UI 的渲染可能会导致什么问题? 那就是过度渲染会导致页面卡顿,这个想必大家应该都遇到过。


3. 60Hz 刷新频率

提到过度渲染,那么就不得不提 60Hz 刷新频率由来:

  • 12 fps :由于人类眼睛的特殊生理结构,如果所看画面之帧率高于每秒约 10-12 帧的时候,就会认为是连贯的。
  • 24 fps :有声电影的拍摄及播放帧率均为每秒 24 帧,对一般人而言已算可接受。
  • 30 fps :早期的高动态电子游戏,帧率少于每秒 30 帧的话就会显得不连贯,这是因为没有动态模 糊使流畅度降低。
  • 60 fps :在与手机交互过程中,如触摸和反馈 60 帧以下人是能感觉出来的。 60 帧以上不能察觉变化,当帧率低于 60 fps 时感觉的画面的卡顿和迟滞现象。

Android 系统每隔 16ms 发出 VSYNC 信号 (1000ms/60=16.66ms) ,触发对 UI 进行渲染, 如果每次渲染都成 功这样就能够达到流畅的画面所需要的 60 fps ,为了能够实现 60 fps ,这意味着计算渲染的大多数操作都必须 在 16ms 内完成。


16 毫秒的时间主要被两件事情所占用:

  • 第一件:将 UI 对象转换为一系列多边形和纹理。
  • 第二件: CPU 传递处理数据到 GPU 。

所以很明显,我们要缩短这两部分的时间,也就是说需要尽量减少对象转换的次数,以及上传数据的次数。


这边提供两个过度绘制的情况:

  • 自定义控件中 onDraw() 方法做了过多重复绘制。
  • xml 布局层次太深,重叠性太强。用户看不到的区域 GPU 也会渲染,导致耗时增加。

4. 查看页面是否过度绘制

那么对于我们自己的项目,如何去查看页面是否过度绘制呢?

  • 手机开发者选项 --> 打卡调试 GPU 过度绘制。
  • 其中颜色代表渲染的图层情况,分别代表 1 层,2 层,3 层,4 层。如下图:
    渲染程度

好了,现在大家可以打开自己的项目,看一看自己项目中的页面,如果页面中红色区域较多,那么明显是需要优化的,尽量都是绿色显示,有些可能业务需要,没办法优化,那就不能强求了。


5. UI 绘制优化方案

每个人的项目都有所不同,需求也不一样,这边就不具体展示 xml 页面如果优化了,我总结了一下我自己优化的几个方案,大家都可以去尝试一下:

1. 减少背景重复:

在自己的项目中对某些布局优化时,可以反问自己,这布局中的背景是否需要,是否可以删除多余的布局,能否用 RelateLayout 减少层级嵌套,实现同样的效果。

  • 主题中的设置:去掉所有 Activity 主题设置中的属性,直接在 styles.xml 文件中设置<item name="android:windowBackground">@null</item>
  • 非业务需要,不要去设置背景。意思是在 xml 文件中,有些整体区域的背景能不设置就不要设置,可以放在子控件中设置,就在子控件中设置。
2. 自定义控件中,对于重叠显示的图片,可以用裁剪的方式,减少重叠部分
3. 能在一个平面显示的内容,尽量只用一个容器;能复用的代码,用include处理,可以减少GPU重复工作:
  • 这边比较推荐的是使用 includemerge 这两种方式。至于具体做法,网上搜索,写的好的文章很多,这边推荐一篇比较不错的文章:Android 布局优化之include与merge,写的很详细了。
4. 使用ViewStub进行布局的懒加载


写在文末

纸上得来终觉浅,绝知此事要躬行。 《冬夜读书示子聿》-- 陆游

好了,关于 UI 绘制优化的思路以及解决方案 就说完了,各位小伙伴可以在项目中借鉴文章中给出的思路优化。


码字不易,如果本篇文章对您哪怕有一点点帮助,请不要吝啬您的点赞,我将持续带来更多优质文章。

发布了13 篇原创文章 · 获赞 14 · 访问量 8395

猜你喜欢

转载自blog.csdn.net/wild_onlyking/article/details/104713081