布局渲染流程

621 阅读4分钟

布局渲染流程

1,之前一篇文章讲解了CPU和GPU的工作原理,不懂的可以去参考参考。

2,60fps刷新频率的由来。

  • 12fps:由于人的眼睛,在每秒约10到12帧之上,人的眼睛看到的画面的帧率认为是连贯的。
  • 24fps:有声电影的拍摄及播放均为24帧,对于一般人而言,可以接受了。
  • 30fps:早起的高动态的电子游戏,帧率少于30帧,会显得不连贯。那是因为没有动态模糊,使流畅度降低。
  • 60fps: 当人和手机交互时,如触摸和反馈,在60帧以下,是人可以感受到变化的,60帧以上是感觉不到变化的。
  • 当画面低于60帧时,会感觉到画面的卡顿或者迟滞现象。

android系统每隔16ms会发出vsync信号(1000ms/60=16.66ms),触发对UI进行渲染,如果每次都成功,这样就能达到流畅的画面所需要的60帧。也就是意味着渲染的大部分操作都必须在16ms内完成。

3,卡顿原理分析

当这一帧画面渲染时间超过16ms的时候,垂直同步机制会让显示器硬件等待GPU完成栅格化渲染操作。 这样这一帧画面就会多等待16ms,甚至更多时间,就会造成画面停顿。 如下图:

4,16ms时间在干什么

  • 第一件事:将UI对象转换为一系列的多边形对象和纹理。
  • 第二件事:CPU传递处理数据到GPU。
  • 所以我们要尽量的减少这两件事的时间,也就是减少UI对象转换和数据之间的传递。

5,如何减少这两部分时间,以至于在16ms内完成。

  • cpu减少xml转换对象的时间。
  • GPU减少重复绘制时间。

6,什么是过度绘制。

GPU的绘制,就像刷墙一样,一层一层的覆盖,16ms绘制一次,这样无用的层,在底部还在绘制,造成浪费。

7,GPU过度绘制的几种情况

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

8,过度绘制查看工具

在手机的开发这选项里面,有GPU调式选项。我们是需要尽量减少红色

  • 蓝色:代表过度绘制一次(无过度绘制)。
  • 淡绿:代表过度绘制两次。
  • 淡红:过度绘制三次。
  • 深红:过度绘制四次。

9,安卓系统有没有给我们做优化呢。

CPU转移到GPU是一件很麻烦的事情,所幸的是OpenGl ES可以把那些需要渲染的纹理Hold在GPU Memory里面,在下次需要渲染的时候直接进行操作,所以如果你更新了GPU所hold住的纹理内容,那么之前保存的状态就丢失了。 在android里面那些由主题所提供的的资源,例如Bitmaps,Drawables都是一起打包到统一的Texture纹理当中,然后再传递到GPU里面,这意味着每次你需要使用这些资源的时候,都是直接从纹理里面进行获取渲染的。当然随着UI组件的越来越丰富,有了更多的演变的形态。例如显示图片的时候,需要先经过GPU的计算加载到内存中,然后传递给GPU进行渲染,然后传递给GPU进行渲染。文字的显示比较复杂,需要先经过CPU换算成纹理,然后交给GPU进行渲染,返回当CPU绘制单个字符的时候,再重新引用经过渲染的内容。动画则存在一个更加复杂的操作流程。 为了能够使得App流畅,我们需要在每帧16ms以内处理完所有的CPU与GPU的计算,绘制,渲染等等操作。

10,布局优化原则

  • 1,减少不必要嵌套。
  • 2,使用merger避免与父容器重叠。

注意:

  • 1,减少过度绘制,其实就是减少CPU的计算时间。
  • 2,调用Invalidate()重绘View时,在7.0之前(不包含7.0),调用Invalidate()时,将会重新调用onMesure(),onLayout(),onDraw()方法。当在7.0之后(包含7.0),调用Invalidate()时,就只调用onDraw()方法,因为当位置变换时,onMesure(),onLayout()方法会自动调用更新,当位置变换的时候,是在先CPU里面更新,然后再发送给GPU更新。当位置不变,只是颜色改变时,就只是在GPU里面更新。