Android过度绘制

一、基础知识

android 的渲染主要分为两个组件:1.CPU 2.GPU,由这两者共同完成在屏幕上绘制 。

  • CPU:中央处理器,它集成了运算,缓冲,控制等单元,包括绘图功能.CPU将对象处理为多维图形,纹理(Bitmaps、Drawables等都是一起打包到统一的纹理)。
  • GPU:一个类似于CPU的专门用来处理Graphics的处理器,用来帮助加快格栅化操作,当然,也有相应的缓存数据(例如缓存已经光栅化过的bitmap等)机制。

  • OpenGL ES:手持嵌入式设备的3DAPI,跨平台的、功能完善的2D和3D图形应用程序接口API,有一套固定渲染管线流程。

  • DisplayList:把XML布局文件转换成GPU能够识别并绘制的对象。这个操作是在DisplayList的帮助下完成的。DisplayList持有所有将要交给GPU绘制到屏幕上的数据信息。

  • 栅格化:将图片等矢量资源,转化为一格格像素点的像素图,显示到屏幕上。

  • 垂直同步VSYNC:让显卡的运算和显示器刷新率一致以稳定输出的画面质量。它告知GPU在载入新帧之前,要等待屏幕绘制完成前一帧。下面的三张图分别是GPU和硬件同步所发生的情况,Refresh Rate:屏幕一秒内刷新屏幕的次数,由硬件决定,例如60Hz.而Frame Rate:GPU一秒绘制操作的帧数,单位fps。

    二、什么是过度绘制?

过度绘制(Overdraw)描述的是屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次重叠的 UI 结构里面,如果不可见的 UI 也在做绘制的操作,会导致某些像素区域被绘制了多次,同时也会浪费大量的 CPU 以及 GPU 资源,绘制示意图如下图所示

overdraw

  • 原色:没有过度绘制

  • 蓝色:1 次过度绘制

  • 绿色:2 次过度绘制

  • 粉色:3 次过度绘制

  • 红色:4 次及以上过度绘制

三、过度绘制优化

1. 去除Activity自带的默认window背景

一般应用默认继承的主题都会有一个默认的 windowBackground ,比如默认的 Light 主题:

<style name="Theme.Light"> 
<item name="isLightTheme">true</item> 
<item name="windowBackground">@drawable/screen_background_selector_light</item>
 ...
  </style>

但是一般界面都会自己设置界面的背景颜色或者列表页则由 item 的背景来决定,所以默认的 Window 背景基本用不上,如果不移除就会导致所有界面都多 1 次绘制。

可以在应用的主题中添加如下的一行属性来移除默认的 Window 背景:

<item name="android:windowBackground">@android:color/transparent</item>
 <!-- 或者 --> 
 <item name="android:windowBackground">@null</item>

或者在 BaseActivity 的 onCreate() 方法中使用下面的代码移除:

getWindow().setBackgroundDrawable(null); 
或者
getWindow().setBackgroundDrawableResource(android.R.color.transparent);

移除默认的 Window 背景的工作在项目初期做最好,因为有可能有的界面未设置背景色,这就会导致该界面显示成黑色的背景,如下所示,如果是后期移除的,就需要检查移除默认 Window 背景之后的界面是否显示正常。

2.移除不必要的背景

还是上面的那个界面,因为移除了默认的 Window 背景,所以在布局中设置背景为白色:

Neil Liu wechat
个人微信,欢迎交流
让我感受下知识的力量~