一、概述

今天,介绍两个比较简单的性能优化工具:

调试 GPU过度绘制 
GPU呈现模式分析

其实这两个工具所解决的问题并不相同,之所以把它们放在一起,是因为它们都是Android手机自带的分析工具,我们只要在设置中对应的开关,就可以实时获得分析的结果,下面,我们就一起来看一下如何使用它们。

二、调试 GPU过度绘制

  • 应用场景

这个工具主要是用来检查布局中是否存在布局层次过深的问题。

  • 过度绘制的概念

如果你粉刷过一个房间或一所房子,就会知道给墙壁涂上颜色需要做大量的工作。假如你还要重新粉刷一次的话,第二次粉刷的颜色会覆盖住第一次的颜色,第一次的颜色就永远不可见了,等于你第一次粉刷做的大量工作就完全被浪费掉。这太可怕了。

同样的道理,如果在你的应用程序中浪费精力去绘制一些东西同样会产生性能问题。过度绘制这个名词就是用来描述屏幕上一个像素在单个帧中被重绘了多少次。

  • 过度绘制分析

过度绘制其实是一个性能和设计的交叉点。我们在设计上追求很华丽的视觉效果,但一般来说这种视觉效果会采用非常多的层叠组件来实现,这时候就会带来过度绘制的问题。比如:我们有一叠UI组件,这些组件从上到下分布,上面的组件是可以被用户看见的,而在下面的组件是不可见的,但是我们依然要花很多时间去绘制那些不可见的组件,因为在某些时候,它也可能会显示出来。但这确实是在浪费CPU和GPU的资源啊

  • 检测过度绘制

进入设置----开发者选项----打开调试GPU过度绘制(Show GPU Overdraw)选项,在弹出框中选择第二项:

打开这个选项后,你的手机会出现一些奇怪的颜色,请不要惊慌,这是正常的。系统正在你的屏幕上通过给像素绘制不同的颜色来
显示这个像素被过度绘制的次数。一共有四种颜色:蓝色、绿色、淡红、深红。根据过度绘制的次数,依次递增

具体图片如下

  1. 蓝色 过度绘制一次(说明这块像素区域绘制了两次)
  2. 绿色 过度绘制两次
  3. 粉色 过度绘制三次
  4. 红色 过度绘制四次
  • 目标和一个简单的方法

你的目标就是尽可能的减少过度绘制,使得你在屏幕更多的看到的是蓝色而不是深红色。

总结和建议

  • 过度绘制产生的原因
  1. 太多重叠的背景
    重叠着的背景有时候是有必要的,有时候是没必要的。这要视你的项目具体情况而定.

  2. 太多叠加的View
    或者本来这个UI布局就很复杂或者你是为了追求一个炫丽的视觉效果,这都有可能使得很多view叠加在一起。这个情况非常普遍,下面的建议中会谈谈怎么减少这种情况带来的影响。

  3. 复杂的Layout层级
    复杂的层级关系,这个在布局中也很常见,下面也会说这种情况怎么做可以尽可能的减少过度绘制。

  • 建议

1.避免“OverDesign”

overdraw会给APP带来不好的体验,overdraw产生的原因无外乎:复杂的Layout层级,重叠的View,重叠的背景这几种。开发人员无节制的View堆砌,究其根本无非是产品无节制的需求设计。有道是“由俭入奢易,由奢入俭难",很多APP披着过度设计的华丽外衣,却忘了简单易用才是王道的本质,纷繁复杂的设计并不会给用户带来好的体验,反而会让用户有压迫感,产品本身也有可能因此变得卡顿。当然,一切抛开业务谈优化都是空中楼阁,这就需要产品设计也要有一个权衡,在复杂的业务逻辑与简单易用的界面展现中做一个平衡,而不是一味的OverDesign。


2.太多重叠的view

第一个建议是:使用ViewStub来加载一些不常用的布局,它是一个轻量级且默认不可见的视图,可以动态的加载一个布局,只有你用到这个重叠着的view的时候才加载,推迟加载的时间。第二个建议是:如果使用了类似viewpager+Fragment这样的组合或者有多个Fragment在一个界面上,需要控制Fragment的显示和隐藏,尽量使用动态地Inflation view,它的性能要比SetVisiblity好。


3.合理选择控件容器

这里的建议比较多一些,首先推荐用Android提供的布局工具Hierarchy Viewer来检查和优化布局。第一个建议是:如果嵌套的线性布局加深了布局层次,可以使用相对布局来取代。第二个建议是:用标签来合并布局,这可以减少布局层次。第三个建议是:用标签来重用布局,抽取通用的布局可以让布局的逻辑更清晰明了。记住,这些建议的最终目的都是使得你的Layout在Hierarchy Viewer里变得宽而浅,而不是窄而深。


4.去掉其他不必要的背景

有时候为了方便会先给Layout设置一个整体的背景,再给子View设置背景,这里也会造成重叠,如果子View宽度mach_parent,可以看到完全覆盖了Layout的一部分,这里就可以通过分别设置背景来减少重绘。再比如如果采用的是selector的背景,将normal状态的color设置为“@android:color/transparent",也同样可以解决问题。这里只简单举两个例子,我们在开发过程中的一些习惯性思维定式会带来不经意的Overdraw,所以开发过程中我们为某个View或者ViewGroup设置背景的时候,先思考下是否真的有必要,或者思考下这个背景能不能分段设置在子View上,而不是图方便直接设置在根View上。


5.ClipRect & QuickReject
为了解决Overdraw的问题,Android系统会通过避免绘制那些完全不可见的组件来尽量减少消耗。但是不幸的是,对于那些过于复杂的自定义的View(通常重写了onDraw方法),Android系统无法检测在onDraw里面具体会执行什么操作,系统无法监控并自动优化,也就无法避免Overdraw了。但是我们可以通过canvas.clipRect()来帮助系统识别那些可见的区域。这个方法可以指定一块矩形区域,只有在这个区域内才会被绘制,其他的区域会被忽视。这个API可以很好的帮助那些有多组重叠组件的自定义View来控制显示的区域。同时clipRect方法还可以帮助节约CPU与GPU资源,在clipRect区域之外的绘制指令都不会被执行,那些部分内容在矩形区域内的组件,仍然会得到绘制。除了clipRect方法之外,我们还可以使用canvas.quickreject()来判断是否没和某个矩形相交,从而跳过那些非矩形区域内的绘制操作。
clip方法详解


6.使用ViewStub占位

ViewStub是个什么东西?一句话总结:高效占位符。我们经常会遇到这样的情况,运行时动态根据条件来决定显示哪个View或布局。常用的做法是把View都写在上面,先把它们的可见性都设为View.GONE,然后在代码中动态的更改它的可见性。这样的做法的优点是逻辑简单而且控制起来比较灵活。但是它的缺点就是,耗费资源。虽然把View的初始可见View.GONE但是在Inflate布局的时候View仍然会被Inflate,也就是说仍然会创建对象,会被实例化,会被设置属性。也就是说,会耗费内存等资源。推荐的做法是使用android.view.ViewStub,ViewStub是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。可以为ViewStub指定一个布局,在Inflate布局的时候,只有ViewStub会被初始化,然后当ViewStub被设置为可见的时候,或是调用了ViewStub.inflate()的时候,ViewStub所向的布局就会被Inflate和实例化,然后ViewStub的布局属性都会传给它所指向的布局。这样,就可以使用ViewStub来方便的在运行时,要还是不要显示某个布局。

  <ViewStubandroid:id="@+id/stub_view"android:inflatedId="@+id/panel_stub"android:layout="@layout/progress_overlay"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_gravity="bottom" />

当你想加载布局时,可以使用下面其中一种方法:

  //方法一((ViewStub) findViewById(R.id.stub_view)).setVisibility(View.VISIBLE);//方法二View importPanel = ((ViewStub) findViewById(R.id.stub_view)).inflate();

7.用Merge减少布局深度
Merge标签有什么用呢?简单粗暴点回答:干掉一个view层级。Merge的作用很明显,但是也有一些使用条件的限制。有两种情况下我们可以使用Merge标签来做容器控件。第一种子视图不需要指定任何针对父视图的布局属性,就是说父容器仅仅是个容器,子视图只需要直接添加到父视图上用于显示就行。另外一种是假如需要在LinearLayout里面嵌入一个布局(或者视图),而恰恰这个布局(或者视图)的根节点也是LinearLayout,这样就多了一层没有用的嵌套,无疑这样只会拖慢程序速度。而这个时候如果我们使用merge根标签就可以避免那样的问题。另外Merge只能作为XML布局的根标签使用,当Inflate以<merge />开头的布局文件时,必须指定一个父ViewGroup,并且必须设定attachToRoot为true。
使用HierarchyViewer检查布局层级

7.善用draw9patch
给ImageView加一个边框,你肯定遇到过这种需求,通常在ImageView后面设置一张背景图,露出边框便完美解决问题,此时这个ImageView,设置了两层drawable,底下一层仅仅是为了作为图片的边框而已。但是两层drawable的重叠区域去绘制了两次,导致overdraw。优化方案: 将背景drawable制作成draw9patch,并且将和前景重叠的部分设置为透明。由于Android的2D渲染器会优化draw9patch中的透明区域,从而优化了这次overdraw。 但是背景图片必须制作成draw9patch才行,因为Android 2D渲染器只对draw9patch有这个优化,否则,一张普通的Png,就算你把中间的部分设置成透明,也不会减少这次overdraw。


8.慎用Alpha
假如对一个View做Alpha转化,需要先将View绘制出来,然后做Alpha转化,最后将转换后的效果绘制在界面上。通俗点说,做Alpha转化就需要对当前View绘制两遍,可想而知,绘制效率会大打折扣,耗时会翻倍,所以Alpha还是慎用。如果一定做Alpha转化的话,可以采用缓存的方式。

   view.setLayerType(LAYER_TYPE_HARDWARE);doSmoeThing();view.setLayerType(LAYER_TYPE_NONE);

通过setLayerType方式可以将当前界面缓存在GPU中,这样不需要每次绘制原始界面,但是GPU内存是相当宝贵的,所以用完要马上释放掉。

参考:https://www.jianshu.com/p/2cc6d5842986

APP性能优化之工具使用- 调试GPU过度绘制相关推荐

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

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

  2. Android系统性能优化(56)---APP性能优化

    Android客户端性能优化(魅族资深工程师毫无保留奉献) 转载学习:http://blog.tingyun.com/web/article/detail/155?from=groupmessage& ...

  3. Android App性能优化总结

    优化方向 Android系统性能已经非常流畅了.但是,到了各大厂商手里,改源码自定系统,使得Android原生系统变得鱼龙混杂,然后到了不同层次的开发工程师手里,因为技术水平的参差不齐,即使很多手机在 ...

  4. App性能优化(布局优化,线程优化,app瘦身优化,页面切换优化,App启动优化,内存优化)

    Android APP性能优化(最新总结) 在目前Android开发中,UI布局可以说是每个App使用频率很高的,随着UI越来越多,布局的重复性.复杂度也随之增长,这样使得UI布局的优化,显得至关重要 ...

  5. Android性能优化之工具篇 — — 开发者选项

    Google为了方便开发者调试Android程序专门开发了开发者选项功能,能够让开发者方便快捷调试Android应用程序.对于一般用户无需关注,所以往往开发者选项在新版本中都会隐藏,需要特殊操作才会展 ...

  6. Android开发者选项之GPU过度绘制

    做设计的人很少能知道GPU过度绘制是个什么鬼?跟设计有什么关系?今天就让大家了解了解,首先来普及一下Android开发者选项中的Debug GPU overdraw. GPU过度绘制定义 如果你粉刷过 ...

  7. Android APP性能优化

    转载自:https://www.cnblogs.com/qwangxiao/p/8727229.html Android APP性能优化(最新总结) 导语 安卓大军浩浩荡荡,发展已近十个年头,技术优化 ...

  8. Android APP性能优化(一)

    Android APP性能优化(最新总结) 安卓大军浩浩荡荡,发展已近十个年头,技术优化日异月新,如今Android 8.0 Oreo 都发布了,Android系统性能已经非常流畅了.但是,到了各大厂 ...

  9. WP7 App性能优化(8):检测应用程序性能(Ⅰ)

    有很多方法监视应用程序的性能并检测性能问题.检测内存占用是其中之一.也可以启用重绘区域着色和视图缓存,从而可视化的监视相关资源的使用情况.也可以打开帧频计数器使其在Windows Phone 7模拟器 ...

最新文章

  1. 二分查找式的debug
  2. vsftp 添加虚拟帐号
  3. php框架设计(图)
  4. Legacy(线段树优化建边跑Dijkstra)
  5. 记录日志的测试软件_教程:测试期间的日志记录
  6. 对MariaDB10.0的Sphinx进行扩展
  7. [react-router] React-Router 4中<Router>组件有几种类型?
  8. 数据结构之基于Java的二叉树实现
  9. OPPO 物联网开放之路
  10. 观测天文角分辨率单位换算
  11. 在线读取office 文件(Word excel 等)
  12. Hadoop 快速入门
  13. 摇一摇加好友功能实现
  14. 前端重要的H标签详解(干货!)最新版
  15. Daz导出模型的部件中英文对照
  16. pear php库,PEARX-不依赖 PEAR 的 PEAR 的 PHP 库
  17. Parallels Desktop 网络初始化失败解决方法
  18. 李开复评论中国人工智能
  19. freemarker bilibi
  20. 【后台定位】Android13后台定位方案

热门文章

  1. Activity、Task、Application关系+Intent启动Flag
  2. centos os u盘启动盘_U盘安装CentOS
  3. 程序员莫名收到谷歌转账170万元,直言:一个月没敢花
  4. 网络工程师试题(一)-2020-12-6
  5. 天津大学902软件工程2019年考研真题回忆
  6. SQL手工注入网站笔记
  7. keep-alive 介绍
  8. 深度学习与自然语言处理(4)_斯坦福cs224d 大作业测验1与解答
  9. 软考高项:信息网络安全知识模拟题
  10. macOS 安装ultraedit