Android UI性能优化 – Overdraw

什么是Overdraw?

Overdraw就是屏幕上某个像素点在同一帧被绘制了多次。在多层布局结构中,不可见部分也会被绘制。举个例子,一个白色页面上有一个按钮。系统首先绘制白色背景,然后在白色背景上绘制按钮,最后在按钮背景上绘制按钮内容。那么按钮和按钮内容就造成了Overdraw。
其实Overdraw是不可避免的,我们要做的是检查Overdraw次数过多的地方,并删掉无用的绘制。

如何检查Overdraw?

在开发者工具中勾选Show GPU overdraw选项,观察UI上的Overdraw情况。


screenshot


该工具会以不同的颜色绘制在屏幕上,标识出该块UI的Overdraw情况。


screenshot


如果是透明色,表示只绘制了一次,没有Overdraw。
我们要做的就是减少大面积的红色区域,使其变成蓝色甚至是透明色。对于深红色,就要思考出了什么问题,坚决进行优化。

优化菜鸟裹裹物流详情页面

首先打开Show GPU overdraw选项,观察一下情况。


screenshot


相当恐怖,几乎全是深红色。

分析Overdraw原因

布局结构:基于ListView展示,快递信息、物品信息、小件员信息在同一个View封装,作为HeaderView加入ListView,ListView的item展示物流跟踪信息。


screenshot

绘制层级:

第一层:window背景
第二层:Activity中fragment container背景
第三层:Fragment中ListView背景
第四层:ListView的Header背景和物流信息item背景
第五层:快递信息、物品信息、小件员信息背景和物流信息item内容
第六层+:快递信息、物品信息、小件员信息内容

开始优化
第一步,删除window默认背景

Android系统提供了默认的背景,被DecorView持有,但是通常情况,我们会为全屏提供自定义颜色,那么这个背景就没用了,反而会带来一次Overdraw的性能损耗。
Activity的onCreate方法中,调用getWindow().setBackgroundDrawable(null)即可删除这个默认背景。
注意,这个方法应该在setContentView后调用。原因通过分析源码可知:
setContentView通过调用PhoneWindow的setContentView,再到installDecor。最终通过以下代码设置背景:

if (mDecor.getBackground() == null &&mBackgroundFallbackResource != 0) {
    mDecor.setBackgroundFallback(mBackgroundFallbackResource);
}

而getWindow().setBackgroundDrawable(null)同样会调用PhoneWindow的以下方法:

public final void setBackgroundDrawable(Drawable drawable) {
    if (drawable != mBackgroundDrawable || mBackgroundResource != 0) {
        mBackgroundResource = 0;
        mBackgroundDrawable = drawable;
        if (mDecor != null) {
            mDecor.setWindowBackground(drawable);
        }
        if (mBackgroundFallbackResource != 0) {
            mDecor.setBackgroundFallback(drawable != null ? 0 : mBackgroundFallbackResource);
        }
    }
}

可以看出,如果先调用getWindow().setBackgroundDrawable(null), setContentView会再次设置背景色。
因此,getWindow().setBackgroundDrawable(null)应该在setContentView之后调用。

第二步,删除布局中重复设置的背景

整个布局基于ListView全屏展示,因此和Activity中fragment container背景冲突,保留其中之一即可,在这里选择删除ListView的背景,由container设置整体背景。


screenshot


优化效果初见成效,满屏的红色没有了,取而代之的是大块的绿色和蓝色,小块淡红色和极少的深红色。

第三步,优化HeaderView

从UI设计来看,HeaderView的几个区块是白色背景,中间用灰色分割。
原来的实现方案是root view设置灰色背景,sub view使用margin暴露root view底色。如下图:


screenshot


这里是存在优化空间的,可以将双层结构改为单层,区块之间的分割使用灰色背景的view即可。修改后的结构如下图:


screenshot


通过布局结构的优化,可以使HeaderView再减少一次Overdraw。

第四步,细粒度优化

观察第二步优化后的情况,可以发现,物品信息TextView和快递图标ImageView还是存在深红色。
检查布局文件发现,TextView设置了和parent view相同的背景色,这很简单,删除即可。
快递图标使用了两个ImageView组成,一个展示快递图标,另一个为图标增加了边框。我将两个ImageView进行合并,通过src属性展示图标,background属性设置边框,并增加了1px的padding把边框展示出来。
而物品图标使用了自定义的ImageView,使用上述优化手段存在bug,暂不做处理。
至此,优化工作完成,下图是优化后的效果。


screenshot


可以看出,整屏基本上都是蓝色,少量绿色以及小面积的淡红色,基本达到了优化效果。

最后,总结一下优化步骤
  1. 删除window默认背景。
  2. 删除多层布局结构中重复设置的背景
  3. 优化布局,减少布局层次。
  4. 检查组件,删繁去冗。
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值