>>分享Android开发相关的技术 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 19940 个阅读者 刷新本主题
 * 贴子主题:  Android性能优化:布局渲染流程及优化 回复文章 点赞(0)  收藏  
作者:javathinker    发表时间:2020-03-08 17:03:30     消息  查看  搜索  好友  复制  引用

                                                                                                

Android性能优化: 布局渲染流程及优化

一、布局渲染流程

     我们平常开发中的那些控件,比如Button,TextView,是如何渲染到屏幕上的呢?

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

         简而言之,就是现先将xml解析成相应的对象,然后CPU经过计算以后将图形信息传给GPU,GPU来负责绘制,栅格化等操作,最终显示到手机屏幕上。    

二、为什么会出现卡顿

     点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

         Android每16ms对屏幕进行一次刷新,当一帧画面渲染时间超过16ms的时候,垂直同步机制会让显示器硬件等待GPU完成栅格化渲染操作,最后在下一次VSync信号到来时才显示到屏幕上,这样就会让这一帧画面,在屏幕上多停留了16ms    

         点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

         如上图

Step1. Display显示第0帧数据,此时CPU和GPU渲染第1帧画面,而且赶在Display显示下一帧前完成

Step2. 因为渲染及时,Display在第0帧显示完成后,也就是第1个VSync后,正常显示第1帧

Step3. 由于某些原因,比如CPU资源被占用,系统没有及时地开始处理第2帧,直到第2个VSync快来前才开始处理

Step4. 第2个VSync来时,由于第2帧数据还没有准备就绪,显示的还是第1帧。这种情况被Android开发组命名为“Jank”。

Step5. 当第2帧数据准备完成后,它并不会马上被显示,而是要等待下一个VSync。

所以总的来说,就是屏幕平白无故地多显示了一次第1帧。原因大家应该都看到了,就是CPU没有及时地开始着手处理第2帧的渲染工作,以致“延误军机”。

         试想用户盯着同一张图看了32ms而不是16ms,当然很容易察觉出卡顿感,哪怕仅仅出现一次掉帧,用户都会发现动画不是很顺畅。    

三、如何解决这种问题

     16 毫秒的时间主要被两件事情所占用

第一件:将 UI 对象转换为一系列多边形和纹理

第二件: CPU 传递处理数据到 GPU 。所以很明显,我们要缩短

这两部分的时间,也就是说需要尽量减少对象转换的次数,以及上传数据的次数

         如何减少这两部分的时间 以至于在 16ms 完成呢?

(1)CPU 减少 xml 转换成对象的时间(去掉重复的、减少不必要的布局,尽量扁平化)

(2)GPU 减少重复绘制的时间    

四、什么是过度绘制

     GPU的绘制过程,就跟刷墙一样,一层一层地进行,16ms刷一次。这样就会造成,图层覆盖的现象,即无用的图层还被绘制在底层,造成不必要的浪费

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

         GPU过度绘制的几种情况    
  1. 自定义控件中,onDraw方法做了过多重复绘制
  2. 布局层次太深,重叠性太强。用户看不到的区域GPU也会渲染,导致耗时增加
     过度绘制查看工具

在手机端的开发者选项里,里面有个调试GPU过度绘制工具

点击以后会发现你的屏幕变得红红绿绿的,这些颜色就代表了特定部分过度绘制的程度    
  • 蓝色:过度绘制一次(无过度绘制)
  • 淡绿:过度绘制两次
  • 淡红:过度绘制三次
  • 深红:过度绘制四次

    我们优化的目的就是尽量减少红色,看到更多蓝色的区域。
     点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

         可以看到,这里的RecyclerView布局列表项重复绘制了四次,导致画面十分卡顿。

         通过分析,我们发现问题有以下几个:    
  1. 背景和主题冲突,重复绘制两次。解决办法,设置主题为null。之后我们发现背景由绿色变为了蓝色,减少了一层绘制
  2. imageView也设置了一个background,导致过度绘制,解决办法,将这个background去掉。之后图片也由淡红变成了绿色。
  3. RecyclerView的item项中多了一层不必要的LinearLayout,将其删除,我们的过度绘制又减少了一层。
     其实还有更多方法来减少过度绘制,优化我们的性能。    
  • ListView,RecyclerView列表项中避免使用LinearLayout多重嵌套,尽量用一个RelativeLayout。
  •   可以在TextView中加上drawableLeft来设置图片,避免使用imageView+TextView的方式。

             因为所有的布局解析都要消耗cpu的计算性能,所以Layout并不是越多越好。

五、自定义View的优化

     自定义View优化的重点主要在Canvas上,例如出现几个View互相层叠时(卡牌式),可以通过裁剪画布防止过度绘制

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小    

六、使用Hierarchy Viewer 优化布局

     在Android Studio 的Android Device Monitor中直接打开这个工具点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

         然后打开我们要检测的app,然后

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

         之后可以看到我们的View树,

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

         看到这个简直崩溃了,太多了。

我们看到视图中几乎所有节点都有三个点,颜色也各不相同

这三个点也是代表着View的Measure, Layout和Draw。

不同颜色意味着不同的速度:

         绿: 表示该View的此项性能比该View Tree中超过50%的View都要快;例如,代表Measure的是绿点,意味着这个视图的测量时间快于树中的视图对象的50%。

黄: 表示该View的此项性能比该View Tree中超过50%的View都要慢;  

红: 表示该View的此项性能是View Tree中最慢的。

         点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

         可以很清楚的分辨清不同View的性能以及Measure, Layout和Draw的时间,通过红色的View节点进去查看,布局是否有不合理之处。

         优化方式    
  • Hierarchy Viewer View树中只有一个子节点且id没有被其他地方使用的布局可以去掉
  • 减少不必要嵌套
  • 使用merge标签避免与父容器重叠。
  • include 复用布局,并且复用的布局可以在GPU里可以高效缓存
----------------------------
原文链接:https://blog.csdn.net/SakuraMashiro/article/details/79006791

程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 flybird 在 2020-03-11 11:07:23 重新编辑]
网站系统异常


系统异常信息
Request URL: http://www.javathinker.net/WEB-INF/lybbs/jsp/topic.jsp?postID=2671

java.lang.NullPointerException

如果你不知道错误发生的原因,请把上面完整的信息提交给本站管理人员