转载请注明出处:http://blog.csdn.net/a740169405/article/details/53896497

过度绘制:

屏幕上某一像素点在一帧中被重复绘制多次,就是过度绘制。
下图中多个卡片跌在一起,但是只有第一个卡片是完全可见的。背后的卡片只有部分可见。但是android系统在绘制时会将下层的卡片进行绘制,接着再将上层的卡片进行绘制。但其实,下层卡片不可见的部分是不需要进行绘制的,只有可见部分才需要进行绘制。

依据过度绘制的层度可以分成:
- 无过度绘制(一个像素只被绘制了一次)
- 过度绘制x1(一个像素被绘制了两次)
- 过度绘制x2(一个像素被绘制了三次)
- 过度绘制x3(一个像素被绘制了四次)
- 过度绘制x4+(一个像素被绘制了五次以上)

查看自己应用的过度绘制情况:

方法一:通过开发者选项开启GPU过度绘制调试
Android手机的开发者选项中有『调试 GPU 过度绘制』的选项:

点开后后选择『显示过度绘制区域』:

方法二:通过adb命令开启GPU过度绘制调试
当然,如果每次都进入系统设置嫌麻烦,可以使用adb命令进行开启和关闭:
开启『调试 GPU 过度绘制』:

adb shell setprop debug.hwui.overdraw show

关闭『调试 GPU 过度绘制』:

adb shell setprop debug.hwui.overdraw false

执行命令之后可能需要重新启动你当前开发的应用。

颜色与过度绘制:

  • 原色:没有过度绘制
  • 蓝色:1 次过度绘制
  • 绿色:2 次过度绘制
  • 粉色:3 次过度绘制
  • 红色:4 次及以上过度绘制

在平时的开发中,如果出现粉色及以上的过度绘制情况。说明过度绘制以及很严重了。需要进行优化。

优化过度绘制:

1. 去除Activity自带的默认背景颜色:
查看Android源码里的Theme主题,如下:

<style name="Theme">...<!-- Window attributes --><item name="windowBackground">@drawable/screen_background_selector_dark</item>...
</style>

也就是说继承Theme这个style的风格,默认情况下,新建一个Activity都是有背景的。正常情况下,很多界面其实是不需要背景的。

下面是华为自带天气APP的首页,我们可以看到文字部分以及图标部分都是绿色,说面已经是第三层过度绘制了,其中背后天气图是一层,文字又是一层,正常来说应该只有两层,也就是文字和图标应该是蓝色。那么这多出来的一层应该就是Activity自带的背景色了。也就是theme里面设置的。

我们只要在自己的AppTheme里面去除该背景色即可:

<style name="AppTheme" parent="android:Theme.Light.NoTitleBar"><item name="android:windowBackground">@null</item>
</style>

或者在Activity的onCreate方法中:

getWindow().setBackgroundDrawable(null);

2.使用Canvas的clipRect和clipPath方法限制View的绘制区域
一个Activity对应有一个Canvas,也就是画布,画布的概念就是一个画板,这个画布提供了很多的API,我们可以通过调用画布的API来绘图以及对画布做一些操作,clipRect方法用来裁切画布上的一个矩形区域,该矩形区域用Rect对象来描述。调用了clipRect之后,画布的可绘制区域减小到和Rect指定的矩形区域一样大小。所有的绘制将限制在该矩形范围之内。这里的裁切概念和PS里的裁切类似。

典型的例子,抽屉布局,找了网易云音乐开刀:

注意观察左侧抽屉打开的时候,抽屉布局和背后布局重叠在一起了,此时整个屏幕一多半都变成了红色,过度绘制严重。

在抽屉布局弹出时,抽屉布局是不透明的,也就是说抽屉布局背后挡住的内容布局是不需要绘制的,而网易云进行了绘制,导致抽屉布局所在区域的像素点绘制了多次。

google官方在android.support.v4.widget包下有DrawerLayout.java类。使用来实现抽屉布局的。该类在重写了drawChild方法:

@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {final int height = getHeight();// 判断是否是内容视图final boolean drawingContent = isContentView(child);int clipLeft = 0, clipRight = getWidth();// 记录当前画布信息final int restoreCount = canvas.save();if (drawingContent) {// 只有在绘制内容视图时才进行裁切final int childCount = getChildCount();for (int i = 0; i < childCount; i++) {final View v = getChildAt(i);if (v == child || v.getVisibility() != VISIBLE ||!hasOpaqueBackground(v) || !isDrawerView(v) ||v.getHeight() < height) {// 如果child是内容视图/视图不可见/视图背景透明/不是抽屉视图/child高度小于父布局高度// 则不做画布裁切continue;}if (checkDrawerViewAbsoluteGravity(v, Gravity.LEFT)) {// 盒子在左侧时裁切的left和rightfinal int vright = v.getRight();if (vright > clipLeft) clipLeft = vright;} else {// 盒子在右侧时裁切的的left和rightfinal int vleft = v.getLeft();if (vleft < clipRight) clipRight = vleft;}}// 裁切画布canvas.clipRect(clipLeft, 0, clipRight, getHeight());}// 绘制子视图final boolean result = super.drawChild(canvas, child, drawingTime);// 回复到裁切之前的画布canvas.restoreToCount(restoreCount);
}

drawChild方法在ViewGroup类的dispatchDraw方法内被调用,用来绘制子视图,DrawerLayout类通过重写该方法,因为在所有孩子视图绘制之前都会调用drawChild方法,但是这里只需要对内容区域视图做裁切,当绘制内容区域视图时,取得抽屉视图的位置信息,如果抽屉视图可见、背景为不透明、抽屉高度和父布局高度一致时,取得抽屉视图左、上、右、下边缘在canvas中的位置信息。接着进行裁切,将内容视图未被挡住的部分区域裁切出来,并把裁切完的canvas交由子View进行绘制,这样,内容区域只有在裁切后的区域才会绘制,其他区域不进行绘制。待子View绘制完之后,恢复Canvas到裁切之前的状态,因为一个Window下的所有View都使用的是同一个Canvas,所以需要恢复状态给其他子View使用。

下面看一个系统里的“下载”APP,使用的是DrawerLayout实现:

应用中虽然内容区域是红色,但是抽屉视图拉出来之后,抽屉视图的过度绘制情况却比内容区域未被挡住的部分少。


3. ImageView的background和imageDrawable重叠
Android中,所有的view均可以设置background。ImageView除了能够设置background之外,还能设置ImageDrawable。

在开发中,很多时候需要显示图片,在图片加载出来之前通常是需要显示一张默认图片的,很多时候会使用ImageView的background属性来设置默认背景图,而imageDrawable来设置需要加载的图片。这样会导致一个问题,当图片加载到页面后,默认背景图被挡住了,但是却仍然然需要绘制,导致过度绘制情况的发生。

解决方案是把背景图和真正加载的图片都通过imageDrawable方法进行设置。


总结

  • Android中一个window对应一个Canvas,window下的所有视图(View/ViewGroup)使用的都是同一个canvas,视图树的父节点在调用子视图的View.draw之前,会对Canvas进行裁切,裁切的区域就是View在屏幕中所占的矩形区域,这也就是为什么超过View边界的内容会被裁切掉的原因。
  • 既然过度绘制值一个像素点被绘制多次,我们只要保证图片或者背景颜色不要叠加在一起即可。正确的方式应该是尽量减少带背景的View产生重叠区域。如果重叠,使用canvas的clipRect进行裁切。
  • 尽量减少视图的深度,来减少视图树的遍历过程。

Android性能优化-过度绘制解决方案相关推荐

  1. Android性能优化一绘制原理分析

    Android应用启动慢,使用时经常卡顿,是非常影响用户体验的,应该尽量避免出现. 1.卡顿的分类 按照场景分可以分为: UI绘制 绘制 刷新 应用启动 安装启动 冷启动 热启动 页面跳转 页面间切换 ...

  2. Android性能优化:那些关于Bitmap图片资源优化的小事

    前言 在 Android开发中,性能优化策略十分重要 本文主要讲解性能优化中的Bitmap 使用优化,希望你们会喜欢 Carson带你学Android性能优化系列文章: Android性能优化:性能优 ...

  3. 【Android 性能优化】布局渲染优化 ( GPU 过度绘制优化总结 | CPU 渲染过程 | Layout Inspector 工具 | View Tree 分析 | 布局组件层级分析 )

    文章目录 一. GPU 过度绘制优化总结 二. CPU 渲染过程 三. CPU 渲染性能调试工具 Layout Inspector 四. Layout Inspector 组件树 DecorView ...

  4. 【Android 性能优化】布局渲染优化 ( 过渡绘制 | 背景设置产生的过度绘制 | Android 系统的渲染优化 | 自定义布局渲染优化 )

    文章目录 一. 背景设置产生的过度绘制 二. Android 系统的渲染优化 1. 透明组件数据传递 2. GPU 存储机制 3. Android 7.0 之后的优化机制 三. 自定义布局渲染优化 一 ...

  5. 【Android 性能优化】布局渲染优化 ( 过渡绘制 | 自定义控件过渡绘制 | 布局文件层次深 | GPU 过渡绘制调试工具 | 背景过度绘制 )

    文章目录 一. 过度绘制 二. 过度绘制两种情况 ( 自定义控件 | 布局文件 ) 三. 过度绘制调试 1. 打开过渡绘制调试工具 2. 过渡绘制调试中不同颜色的含义 3. 过渡渲染示例 四. 背景过 ...

  6. 【Android 性能优化】布局渲染优化 ( CPU 渲染优化 | 减少布局的嵌套 | 测量布局绘制时间 | OnFrameMetricsAvailableListener | 布局渲染优化总结 )

    文章目录 一. 减少布局嵌套 二. 布局渲染时间测量 1. FrameMetrics 使用流程 2. FrameMetrics 参数解析 3. FrameMetrics 代码示例 三. 布局渲染优化总 ...

  7. Android之GPU过度绘制与图形渲染优化

    原址 前言 本文主要对过度绘制和图形渲染做一个概念性的描述. 同时以案例方式列出一些简单适用的优化措施. 如果你已对过度绘制有过一些了解,那么你应该明白,仅是简单的层级优化对过度绘制的改善是很小的.所 ...

  8. android过渡渲染,android 性能优化 - 渲染 - 过渡绘制

    1.过渡绘制 Overdraw(过度绘制)描述的是屏幕上的某个像素在同一帧的时间内被绘制了多次.在多层次重叠的UI结构里面,如果不可见的UI也在做绘制的操作,会导致某些像素区域被绘制了多次.这样就会浪 ...

  9. Android性能优化典范笔记(1)-GPU绘制性能优化

    Android性能优化典范笔记(1)-GPU绘制性能优化 你还可以再Github上找到我的这篇文章:https://github.com/onlynight/ReadmeDemo/tree/maste ...

  10. 【Android 性能优化】应用启动优化 ( 阶段总结 | Trace 文件分析及解决方案 | 源码分析梳理 | 设置主题的方案总结 ) ★

    文章目录 一. 常用的耗时方法优化方案 ( 重要 ) 二. 源码分析梳理 1. 应用启动时间计算相关源码分析 2. Launcher 应用中启动 Android 应用流程 三. 启动白屏解决方案 An ...

最新文章

  1. Linux 内核启动流程
  2. 暑期集训1:C++STL 例2:UVA-10935
  3. 从0移植uboot (二) _uboot启动流程分析
  4. 安装yaml报错:ERROR: Cannot uninstall 'PyYAML'.
  5. 组合搜索(combinatorial search)在算法求解中的应用
  6. P1972 [SDOI2009]HH的项链
  7. jquery 给iframe里的元素添加事件
  8. hessianphp java_hessian 在PHP中的使用
  9. 多实例多进程网络编程PHP,php socket网络编程基础知识(四):多进程
  10. pe常用软件_装机不求人之打造自己的全功能PE系统维护优盘
  11. asp.net园林绿化服务交易网站(三层架构)案例
  12. VB入门在线视频教程大全学习
  13. 毕小朋《精通Android studio》读后感,以及电子书百度网盘PDF下载
  14. 腾讯云实验室:搭建 LNMP 环境
  15. 微信怎么自动加好友java_iOS逆向开发之微信自动添加好友功能
  16. 文件服务器磁盘配额管理,文件服务器磁盘配额的管理.doc
  17. 微信小程序用户登录信息过期处理
  18. 蚁剑软件的配置与应用
  19. 以窗口形式进行数字图像处理时,在图像边界处对超出图像边界的窗口内容的映射(对称)处理
  20. Xcode 错误整理

热门文章

  1. 可方向导不一定连续的例子
  2. java 转换成maven项目_java – 将现有项目转换为maven项目
  3. 通俗有趣讲解Atomic原子类的实现原理
  4. android打开视频噔_Android、iOS不可错过!10款堪称神器的高质量APP,请低调使用...
  5. linux wc -l命令,Linux wc sort和uniq的用法
  6. linux安装并行geant4,Ubuntu下安装Geant4精选.pdf
  7. 进程外Session(用数据库)
  8. PKUWC2018 5/6
  9. 【转】Java中的static关键字解析
  10. Spring AOP之静态代理