Android性能优化(4):UI渲染机制以及优化

本文深入探讨了Android应用的UI渲染机制,包括CPU与GPU的角色、渲染流程以及可能导致卡顿的原因。介绍了过度绘制的概念及其优化方法,如使用GPU overdraw工具和Profile GPU Rendering。此外,还分析了卡顿现象,提出了使用SysTrace和TraceView进行性能分析和优化的策略,帮助开发者提升应用的流畅性。
摘要由CSDN通过智能技术生成

从Android 6.0源码的角度剖析View的绘制原理一文中,我们了解到View的绘制流程有三个步骤,即measure(测量)、layout(布局)和draw(绘制),它们主要运行在系统应用框架层,而真正将数据渲染到屏幕上的则是系统Native层的SurfaceFlinger服务来完成的。本文将暂不对SurfaceFlinger服务的执行流程进行剖析,而是从更加底层的角度来了解APP的渲染机制,同时引出在渲染过程中遇到的性能问题,以及如何去发现、优化它们。

1. 渲染机制分析

1.1 渲染机制

 对于开发者来说,APP的界面主要是由XML布局文件来表现的,每个XML布局文件中又包括了很多视图组件,比如ImageView、Button、TextView等等,它们分别表示了图片、按钮、字符串等不同的信息,那么这些复杂的XML布局文件和标记语言,又是如何转化成为用户能够看得懂的图像的呢?答案是:格栅化(Rasterization)!所谓格栅化,就是将例如字符串按钮路径或者形状等的一些高级对象,拆分到不同的像素屏幕上进行显示。格栅化是一个非常费时的操作,CPU作为中央处理器本身任务就比较繁重,因此人们引入了GPU(图像处理器)这块特殊的硬件来加快格栅化操作(硬件加速)。格栅化操作大体如下:
在这里插入图片描述
 接下来,我们就来详细了解XML布局文件中的UI组件是如何被格栅化并渲染显示在屏幕上的?在APP绘制渲染过程中,与绘制渲染有关的硬件主要有CPUGPU(图形处理器),其中,CPU负责把UI组件计算成Polygons(多边形)Texture(纹理),而GPU负责格栅化和渲染工作。CPU和GPU通过图形驱动层进行连接,这个图形驱动层维护了一个Display List队列,它们分别充当生产者消费者,协作完成具体的绘制渲染过程。绘制渲染过程如下图所示:
在这里插入图片描述

  • 渲染流程如下:

首先CPU会对UI组件(View)进行MeasureLayoutRecordExecute的数据计算工作,以将其计算成的Polygons(多边形)Texture(纹理),它们是GPU能够识别的对象,而承载这些信息的是一个被称为Display List的结构体,它持有所有交给GPU绘制到屏幕上的数据信息,包含GPU要绘制的全部对象的信息列表和执行绘制操作的OpenGL命令列表。在某个View第一次需要被渲染的时候,Display List会因此被创建,当这个View需要显示到屏幕上时,GPU接收到绘制指令后会执行该Display List。每个View拥有自己的Display ListDisplay Lis本身也构成一个树状的结构,跟View Hierachy(视图树)保持一致。
在这里插入图片描述
其次,由于每次从CPU计算得到的PolygonsTexture提交(转移)GPU是一件比较麻烦且耗时的事情(注:实际提交的是Display List),因此Android系统又引入了OpenGL ES,该库API允许将那些需要渲染的PolygonsTexture存储(Hold)在GPU存储器(显存)中,当下一次需要渲染的时候只需要在GPU存储器里引用它,然后告诉OpenGL如何绘制就可以了,而不再需要经过CPU上传。需要注意的是,假如View的绘制内容发生变化,那么GPU Memory存储的Display List就无法再继续使用,这时就需要CPU重新计算创建Display List并重新执行指令更新到屏幕。
在这里插入图片描述
 最后,当GPU完成对纹理的格栅化、渲染后,它会将渲染的结果放入帧缓冲区,视频控制器会按照VSync(垂直同步)信号逐行读取帧缓冲区的数据,经过可能的数模转换传递给显示器显示。

  • CPU、OpenGL与GPU之间的关系
    在这里插入图片描述

1.2 卡顿现象

 前面说到,当GPU渲染完成后会将渲染的结果存储到帧缓冲区,视频控制器会按照VSync(垂直同步)信号逐行读取帧缓冲区的数据,经过可能的数模转换传递给显示器显示。那么问题来了,什么是VSYNC信号?在讲解VSYNC之前,我们需要了解两个相关的概念:Refresh RateFrame Rate

  • Refresh Rate(刷新频率)

 表示屏幕在一秒内被刷新的次数,取决于硬件的固定参数,目前大部分手机这个固定参数(屏幕刷新频率)为60Hz。也就是说,Android系统每隔约16ms(1000ms/60=16.66ms)就会重新刷新一次界面(Activity),因此我们有16ms的时间去完成每帧的绘制、渲染的逻辑操作。
在这里插入图片描述

  • Frame Rate(帧率)

 表示GPU在一秒内能够渲染的帧数,通常为60fps。为什么是60fps?这是因为人眼与大脑之间的协作无法感知超过60fps的画面更新。简单的说,人眼看到的动画其实都是一帧帧连续播放的静态图片,当播放的速度达到1秒针24帧(24fps)时,对于人眼感知来说就是连续的线性运动。当然低于30fps在某些场景仍然无法顺畅表现绚丽的画面,此时就需要60fps来达到想要的效果。

 现在我们再来理解下VSYNC信号:**屏幕的刷新过程是每一行从左到右(水平刷新,Horizontal Scanning),从上到下(垂直刷新,Verical Scanning)。当整个屏幕刷新完毕,即一个垂直刷新周期完成,会有短暂的空白期,此时Android系统就会发出VSYNC信号,触发下一帧对UI的渲染、显示。VSYNC是一种定时中断,一旦收到VSYNC信号CPU就开始处理帧数据,通常Android系统每隔16ms发出VSYNC信号,这个周期时间由屏幕刷新频率决定。**通常来说,帧率超过刷新频率只是一种理想的状态,在超过60fps的情况下,GPU所产生的帧数据会因为等待VSYNC的刷新信息而被Hold住,这样能够保持每次屏幕刷新都有实际的新的数据可以显示。但是基本上我们遇到的是帧率<=屏幕刷新频率的情况,尤其是在帧率小于刷新频率时,会出现待VSYNC信号到来时,屏幕没有可以刷新的数据,即帧缓冲区还是之前的那帧图像,这就会导致屏幕显示的该帧画面内容仍然是上一帧的画面,而这种现象我们就称之为"掉帧",对于用户来说,就是界面出现了卡顿现象,即运行不流畅。
在这里插入图片描述
 由此我们可以得出,

  • 12
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值