Android性能优化之——渲染篇

《Android 性能优化》学习课程是Google发布在Udacity(优城学院)的专题课程,它分别从渲染,运算与内存,电量几个方面介绍了如何去优化性能,在这之前国内腾讯的Android大牛——胡凯,对其翻译整理了一份专题博客。但是之前我一直没有博客,但是现在有了,我打算自己去学习课程,自己在他的基础上去完善总结一下相关的课程笔记,毕竟每个人获取知识的重点可能不一样。

今天就从性能优化——渲染篇,开始…

说到Android性能,不得不说一下光头哥Colt McAnlis这位大神,Colt McAnlis是在Google主要从事Android中性能相关工作的,我每次很喜欢看他讲,幽默诙谐,对Android性能方面有很深入的研究,也是我敬仰的Google大神之一

应用性能优化的步骤

  • 获取信息
  • 分析数据
  • 采取行动

设计 vs 性能

现在众多开发APP的公司,为了让App达到很炫丽的视觉冲击效果,会需要在界面上层叠很多的视图组件,很多开发者在开发中注重的基本上都是达到这样的功能效果仅此而已,大多数可能都不会去关心性能是如何的? 只要App功能正常不出异常,那么这款App差不多就OK了,但是往往这样缺乏性能优化的App在用户的手上使用时,回出现各种卡顿、黑屏的情况,致使用户最终不得不卸载你的这款应用。所以我们在开发一款应用的时候,不仅要实现它的功能,性能也不要忽视。

rebder_1

系统会每隔16s重新绘制一次activity,1000ms/60hz=16.666ms/frame

rebder_2

如果在1000/60=16.67ms内没有办法把这一帧的任务执行完毕,就会发生丢帧的现象。丢帧越多,用户感受到的卡顿情况就越严重。

Android CPU 和 GPU

导致卡顿的第一个原因就是:渲染

渲染操作通常依赖于两个核心组件:CPUGPU

rebder_3

CPU方面的因素:不必要的布局和失效 ,这些内容必须在视图层次结构中进行测量、清除并重新创建。一方面,重建显示列表的次数太多,另一方面花费太多的时间在作废视图层并进行不必要的重绘,使更新显示列表或者其他缓存资源时导致cpu工作过度,出现了卡顿。

rebder_4

GPU方面的因素:像素着色过程中,通过其他工具进行后去着色时浪费里GPU处理时间。

rebder_5

Activity的显示?

colt 说: 要想开发一款性能优越的应用,你必须了解底层是如何运行的。

Activity是如何绘制到屏幕上的?复杂的XML布局文件和标记语言是如何转化成用户能看懂的图像的?

答案是:‘格栅化’操作

rebder_6

格栅化:将字符串、按钮、路径或者形状等拆分到不同的像素上在屏幕上进行显示。==> GPU 完成这一操作

rebder_7

GPU使用一些指令的基础指令集,主要是多边形和纹理,也就是图片

rebder_8

CPU在屏幕上绘制图像前,会向GPU输入这些指令,这一过程通常使用的API就是Android的OpengGL ES

UI对象 => CPU转换为多边形或者纹理 ==> GPU格栅化

在Android里面那些由主题所提供的资源,例如Bitmaps,Drawables都是一起打包到统一的Texture纹理当中,然后再传递到GPU里面,这意味着每次你需要使用这些资源的时候,都是直接从纹理里面进行获取渲染的。当然随着UI组件的越来越丰富,有了更多演变的形态。例如显示图片的时候,需要先经过CPU的计算加载到内存中,然后传递给GPU进行渲染。文字的显示比较复杂,需要先经过CPU换算成纹理,然后交给GPU进行渲染,返回到CPU绘制单个字符的时候,再重新引用经过GPU渲染的内容。动画则存在一个更加复杂的操作流程。

为了能够使得App流畅,我们需要在每帧16ms以内处理完所有的CPU与GPU的计算,绘制,渲染等等操作。

渲染性能优化就是:尽可能地上传数据到GPU,然后尽可能长的在不修改的条件下保存数据

GPU性能问题瓶颈:过度绘制

过度绘制

定义:指的是屏幕上的某个像素点在同一帧的时间里被绘制多次

rebder_9

工具:开发者选项 => “Debug GPU overdraw” ==> show

overdraw_options_view

(1x (这个像素点被绘制了2次) 是蓝色,然后还有2x 3x 4x)

蓝色,淡绿,淡红,深红代表了4种不同程度的Overdraw情况,我们的目标就是尽量减少红色Overdraw,看到更多的蓝色区域。

两种清除过度绘制的方法:

  • 要从视图中清除哪些不必要的背景和图片,它们不会在最终渲染的图像中显示
  • 对视图中重叠的屏幕区域进行定义,从而降低CPU和GPU的消耗

剪辑

剪辑:Android 设法避免绘制哪些最终界面中不显示的UI组件,你能确定某个对象会被完全阻挡,那就没必要去绘制它,这时候就需要剪辑

剪辑无法应对复杂的自定义View (比如纸牌层叠), 这时候就需要使用 Canvas.clipRect (ClipRect API 帮助系统识别出无需绘制的区域)

DisplayList

定义: Android需要把XML布局文件转换成GPU能够识别并绘制的对象。这个操作是在DisplayList的帮助下完成的,持有所有要交给GPU绘制到屏幕上的数据信息列表

请注意:任何时候View的绘制内容发生了变化,都需要重新执行DisplayList,并重新执行指令更新到屏幕上,渲染DisplayList,更新到屏幕上等一系列操作。这个流程的表现性能取决于你的View的复杂程度,View的状态变化以及渲染管道的执行性能。

Hierarchy Viewer

rebder_10

打开步骤:Android Studio => Tools => Android => Android Devices Monitor

rebder_11

Hierarchy的好用之处:它能帮助你从Android的角度去理解你的用户界面的结构,同时可以帮助你确定哪些视图是多余的

Venn图形图标,绿黄红三种颜色的圆点表示了渲染速度的快慢,最左边的圆点代表渲染管道的测量阶段,中间的表示布局阶段,最右边的表示渲染管道的绘制阶段

层级扁平化

提升布局性能的关键点是尽量保持布局层级的扁平化,避免出现重复的嵌套布局。

以上就是个人对《Android 性能优化之——渲染篇》的主要内容进行的总结,后面有空继续总结下一篇性能优化的笔记

if (本文对您有用) { Pay (请随意¥打赏) } else { Commit feedback (底部评论区提交建议、反馈) } 感谢支持!