Android Performance: Overdraw的定位

  Android Performance系列的内容整理自UdacityAndroid Performance课程,是对该系列课程的笔记和总结。

  过度绘制(Overdraw)指的是一个像素在一帧里被绘制了多次,旧的绘制会被新的绘制覆盖,是无效的,造成对GPU的浪费。Overdraw通常发生于多个元素重合的情况,位于上层的元素会覆盖住下层的元素,使下层的元素不可见,此时如果还对下层元素进行绘制,就会发生Overdraw。

0. 示例代码

  下面使用的代码可以在这里找到,应用模拟了一个聊天App的界面,如图1所示。

图1

图1

1. 可视化Overdraw

  Android提供了可视化Overdraw的工具,用于定位发生Overdraw的区域,只需在开发者模式的选项中点击“Debug GPU overdraw”,并选择“Show overdraw areas”即可。

图2

  此时回到之前的App,界面如图3。

图3

  不同的背景颜色代表了不同的Overdraw次数,如图4所示:

  • 原色:没有Overdraw
  • 蓝色:一次Overdraw
  • 绿色:两次Overdraw
  • 粉色:三次Overdraw
  • 红色:四次以上Overdraw
图4

图4

2. 移除不必要的填充背景

  从图3中背景的大片绿色可以猜测这里手动设置了一个纯色的背景,导致整个应用的背景发生Overdraw。在activity_chatum_latinum.xml可以看到,这里设置了一个白色被背景@android:color/white

  为了移除这里的背景,除了直接修改上面的android:background,还可以使用getWindow().setBackgroundDrawable(null)。修改ChatumLatinumActivity.java的onCreate()如下:

  此时App的背景变成蓝色,Overdraw减少了一次,如图5。

图5

图5

  除了activity_chatum_latinum.xml,在chat_item.xml和fragment_chats.xml中还有4个不必要的背景,全部删除后,Overdraw大幅减少,如图6。

图6

图6

3. 根据实际需要添加背景

  注意图6中的头像大部分是绿的,说明头像发生了两次Overdraw;其中有一个空头像是蓝色的,说明头像为空时发生了一次Overdraw。在ChatAdapter.java的getView()中可以看到头像的相关逻辑。

这里无论是否有头像,都会使用setBackgroundColor()添加背景,当头像部位空时,就会发生Overdraw,修改这里的逻辑为只在头像为空时才添加背景:

  此时Overdraw进一步减少,如图7。

图7

图7