OverDraw定义

OverDraw就是在某个像素点同一帧内被绘制了多次。最优情况是一个像素每次只被绘制一次。
在多层布局中,不可见部分也会被绘制,这就产生了额外开销。
OverDraw是不可避免的!我们需要做的是将OverDraw过多的部分去掉,删掉一些无用的绘制,尽量优化。

OverDraw检测

Android提供了工具
在开发者选项---硬件加速渲染---调试GPU过度绘制


工具会标识出OverDraw的情况

 

透明--->没有overdraw。完美。
蓝色--->1倍overdraw。绘制两次。可以忍。大面积的话,考虑是否可以干掉一层。
绿色--->2倍overdraw。绘制三次。面积不大的绿色区域可以忍。可尝试优化。
浅红--->3倍overdraw。绘制四次,面积小的浅红可以忍。一般就是写文字按钮什么的。
暗--->4倍及以上overdraw。绘制五次或更多。不能忍!!!肯定可以优化!

优化原则

避免绘制不可见元素!(OverDraw就是一个像素画多了)

优化手段

. 优化Layout的布局结构
  1. layout提倡扁平化,层级越少性能越好。
  2. 层级一样,控件数一样,优先选择LL。(不过,这种小的优化,只有在层级高的时候才会有体现;可惜高层级本来就要规避。)
  3. 利用merge去分割一些layout。Merge会沿用他的父viewlayout的,本身并没有多一层。

. 去掉window的默认背景
  在某些Theme会有默认的黑色背景,如果是Light,可能是白色背景。这也是一个图层。DecorView会持有这个background,而一般是无用的。
Activity的onCreate方法中,调用getWindow().setBackgroundDrawable(null)即可删除这个默认背景。
注意.这个方法应该在setContentView之后调用。
上一段源码解析:ActivitysetContentView最终会调用到PhoneWindow.javasetContentView.
    @Override

    public void setContentView(int layoutResID) {

        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window

        // decor, when theme attributes and the like are crystalized. Do not check the feature

        // before this happens.

        if (mContentParent == null) {

            installDecor();

        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {

            mContentParent.removeAllViews();

        }

        ......

    }
    继续看installDecor()如何实现

    private void installDecor() {

        ......

        if (mContentParent == null) {

            mContentParent = generateLayout(mDecor);

 

            ......

 

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

                mDecor.setBackgroundFallback(mBackgroundFallbackResource);

            }

            ......

        }

    }
    可以看到mDecor会setBackgroundFallback。所以,如果在setContentView之前调用getWindow().setBackgroundDrawable(null)是无效的。必须在setContentView之后。

. 针对系统自带widget-简化没必要的背景
  举例来说,一些ListView是fill_parent的,而有时候为了方便又为容器控件设置了background.这就造成了overdraw。同样如果有一些没必要的TextView有这样的重复layout也是需要剔除的。还有一些Button。在Normal状态可以沿用底层background,或者底层background根本不需要。通过selector将normal的background设置为@android:color/transparent

. 针对自定义onDraw的View--ClipRect
  对于过于复杂的自定义View,Android系统无法检测具体onDraw执行了什么,就无法监控并自动优化。
  1. 我们可以用canvas.clipRect制定一块需要被绘制的区域。其他区域就会被忽略。
  2. 还可以用canvas public boolean quickReject(Rect r)来判断是否没和某矩阵相交
  先看一张图
  
  是不是一下子就少了很多需要绘制的区域。

. 利用draw9patch
  Andrid的2D渲染会优化.9的图片的透明部分。所以偶尔有大图片的时候,这不仅可以减小apk大小,还可以减少overdraw。

. 慎用Alpha变化
  alpha变化包括两个操作
  1. 先绘制出不透明的View
  2. 进行alpha变化
  这就是两次的绘制。要尽量避免。不过有时候拗不过产品,注意一些延迟触发的方法,比如ViewStub,这种高效占位符还是比较好使的。延迟绘制。

. 警惕过度设计
  华丽的设计基本上就是Overdraw的创造者。你懂的。无解。不过可以据理力争。再牛逼的开发都抵不过超复杂的产品


更多相关文章

  1. android背景优化
  2. 某android平板项目开发笔记----aChartEngine图表显示(1)
  3. 内存使用总结篇 -- Android(安卓)内存优化第五弹
  4. Android(安卓)Canvas简单使用
  5. android的DALVIK虚拟机简介
  6. Android(安卓)绘制圆形进度条
  7. Android性能优化系列---管理你的app内存(一)
  8. 玩转 Android(安卓)MediaPlayer之视频预加载(优化)
  9. Android(安卓)View的绘制流程(一)

随机推荐

  1. 关于NavicatPremium导入CSV文件乱码的问
  2. 查询表中的某一行,表中没有行号相关的属性
  3. 在VS下用C语言连接SQLServer2008
  4. 基于GUI和SQL的剧院票务管理系统
  5. mysql5.6和5.7的权限密码设置
  6. JOIN vs. WHERE:为什么获得相同结果的两
  7. hibernate连接mysql,不能自动建表和添加数
  8. 数据库实践二:高级sql语句
  9. 利用LVS+Keepalived实现MySQL高可用1
  10. 简单统计报表例子(存储过程)