优化性能一般从渲染,运算与内存,电量三个方面进行,今天开始说聊一聊Android的渲染机制,我们要知道Android系统每隔16ms就重新绘制一次Activity,也就是说,我们的应用必须在16ms内完成屏幕刷新的全部逻辑操作,即每一帧只能停留16ms,渲染机制说完之后,然后在说如何去优化UI。

1.知识储备
CPU: 中央处理器,它集成了运算,缓冲,控制等单元,包括绘图功能.CPU将对象处理为多维图形,纹理(Bitmaps、Drawables等都是一起打包到统一的纹理).

GPU:一个类似于CPU的专门用来处理Graphics的处理器, 作用用来帮助加快格栅化操作,当然,也有相应的缓存数据(例如缓存已经光栅化过的bitmap等)机制。

OpenGL ES是手持嵌入式设备的3DAPI,跨平台的、功能完善的2D和3D图形应用程序接口API,有一套固定渲染管线流程. 附相关OpenGL渲染流程资料

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

格栅化 是 将图片等矢量资源,转化为一格格像素点的像素图,显示到屏幕上,过程图如下.

2.渲染机制分析
渲染流程线
UI对象—->CPU处理为多维图形,纹理 —–通过OpeGL ES接口调用GPU—-> GPU对图进行光栅化(Frame Rate ) —->硬件时钟(Refresh Rate)—-垂直同步—->投射到屏幕

渲染时间线
Android系统每隔16ms发出VSYNC信号(1000ms/60=16.66ms),触发对UI进行渲染, 如果每次渲染都成功,这样就能够达到流畅的画面所需要的60fps,为了能够实现60fps,这意味着计算渲染的大多数操作都必须在16ms内完成。

正常情况

渲染超时,计算渲染时间超过16ms
当这一帧画面渲染时间超过16ms的时候,垂直同步机制会让显示器硬件 等待GPU完成栅格化渲染操作, 
这样会让这一帧画面,多停留了16ms,甚至更多.这样就这造成了 用户看起来 画面停顿.

当GPU渲染速度过慢,就会导致如下情况,某些帧显示的画面内容就会与上一帧的画面相同

3.渲染时会出现的问题
GPU过度绘制
GPU的绘制过程,就跟刷墙一样,一层层的进行,16ms刷一次.这样就会造成,图层覆盖的现象,即无用的图层还被绘制在底层,造成不必要的浪费.

UI对象—->CPU处理为多维图形,纹理 —–通过OpeGL ES接口调用GPU—-> GPU对图进行光栅化(Frame Rate ) —->硬件时钟(Refresh Rate)—-垂直同步—->投射到屏幕

1、为什么是16ms

16ms意味着1000/60hz,相当于60fps。这是因为人眼与大脑之间的协作无法感知超过60fps的画面更新。12fps大概类似手动快速翻动书籍的帧率, 这明显是可以感知到不够顺滑的。24fps使得人眼感知的是连续线性的运动,这其实是归功于运动模糊的效果。 24fps是电影胶圈通常使用的帧率,因为这个帧率已经足够支撑大部分电影画面需要表达的内容,同时能够最大的减少费用支出。 但是低于30fps是 无法顺畅表现绚丽的画面内容的,此时就需要用到60fps来达到想要的效果,超过60fps就没有必要了。如果我们的应用没有在16ms内完成屏幕刷新的全部逻辑操作,就会发生卡顿。**

2、为什么16ms没完成绘制就会卡顿

Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,VSync是Vertical Synchronization(垂直同步)的缩写,是一种在PC上很早就广泛使用的技术,可以简单的把它认为是一种定时中断。而在Android 4.1(JB)中已经开始引入VSync机制。

3、渲染原理

上面说了CPU和GPU的处理时间因为各种原因都大于一个VSync的间隔(16.6ms),导致了卡顿。渲染操作通常依赖于两个核心组件:CPU与GPU。CPU负责包括Measure,Layout,Record,Execute的计算操作,GPU 负责Rasterization(栅格化)操作

分析到这里,16毫秒的时间主要被两件事情所占用,第一件:将UI对象转换为一系列多边形和纹理;第二件:CPU传递处理数据到GPU。所以很明显,我们要缩短这两部分的时间,也就是说需要尽量减少对象转换的次数,以及上传数据的次数

4、过度绘制(overdraw)*检测

Overdraw(过度绘制)描述的是屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次的UI结构里面, 如果不可见的UI也在做绘制的操作,这就会导致某些像素区域被绘制了多次。这就浪费大量的CPU以及GPU资源。

按照以下步骤打开Show GPU Overrdraw的选项:设置 -> 开发者选项 -> 调试GPU过度绘制 -> 显示GPU过度绘制

5、Overdraw 的处理方案

  • Overdraw 的处理方案一:去掉window的默认背景
    当我们使用了Android自带的一些主题时,window会被默认添加一个纯色的背景,这个背景是被DecorView持有的。当我们的自定义布局时又添加了一张背景图或者设置背景色,那么DecorView的background此时对我们来说是无用的,但是它会产生一次Overdraw,带来绘制性能损耗。去掉window的背景可以在onCreate()中setContentView()之后调用getWindow().setBackgroundDrawable(null);或者在theme中添加android:windowbackground="null";

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

  • Overdraw 的处理方案三:clipRect的使用
    我们可以通过canvas.clipRect()来 帮助系统识别那些可见的区域。这个方法可以指定一块矩形区域,只有在这个区域内才会被绘制,其他的区域会被忽视。这个API可以很好的帮助那些有多组重叠 组件的自定义View来控制显示的区域。同时clipRect方法还可以帮助节约CPU与GPU资源,在clipRect区域之外的绘制指令都不会被执行,那些部分内容在矩形区域内的组件,仍然会得到绘制。

  • Overdraw 的处理方案四:ViewStub
    ViewStub称之为“延迟化加载”,在教多数情况下,程序无需显示ViewStub所指向的布局文件,只有在特定的某些较少条件下,此时ViewStub所指向的布局文件才需要被inflate,且此布局文件直接将当前ViewStub替换掉,具体是通过viewStub.infalte()或viewStub.setVisibility(View.VISIBLE)来完成;

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

布局常见问题与优化建议

  • 没有用的父布局时指没有背景绘制或者没有大小限制的父布局,这样的布局不会对UI效果产生任何影响。我们可以把没有用的父布局,通过<merge/>标签合并来减少UI的层次;
  • 使用线性布局LinearLayout排版导致UI层次变深,如果有这类问题,我们就使用相对布局RelativeLayout代替LinearLayout,减少UI的层次;
  • 不常用的UI被设置成GONE,比如异常的错误页面,如果有这类问题,我们需要用<ViewStub/>标签,代替GONE提高UI性能。

android屏幕渲染机制相关推荐

  1. Android 屏幕刷新机制

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 这次就来梳理一下 Android 的屏幕刷新机制,把我这段时间因为研究动画而梳理出来的一些关于屏幕刷新方面的知识点分享出来,能力有限 ...

  2. 关于Android Framework渲染机制,你需要学习哪些?

    聊到Android的渲染流程部分,部分Android开发脑海中估计又会想起面试官在面试时提出的那些死亡面试题: Android渲染的整体架构是怎样的? Android渲染的生产者包括哪些?Skia与O ...

  3. android屏幕刷新显示机制

    title: android屏幕刷新显示机制 tags: 新建,模板,小书匠 grammar_cjkRuby: true android屏幕刷新显示机制 前言 本文是通过阅读各种文章及代码,总结出来的 ...

  4. Android屏幕刷新机制

    Android屏幕刷新机制 一些前置概念 屏幕刷新率 一秒内屏幕刷新的次数(一秒内显示了多少帧的图像),单位 Hz(赫兹),如常见的 60 Hz,90Hz,120Hz(高刷新率).刷新频率取决于硬件的 ...

  5. Android屏幕刷新机制—VSync、Choreographer-全面理解

    2.2.3 VSync 问题又来了:什么时候进行两个buffer的交换呢? 假如是 Back buffer准备完成一帧数据以后就进行,那么如果此时屏幕还没有完整显示上一帧内容的话,肯定是会出问题的.看 ...

  6. “终于懂了” 系列:Android屏幕刷新机制—VSync、Choreographer 全面理解!

    文章目录 一.背景和疑问 二.显示系统基础知识 2.1 基础概念 2.2 双缓存 2.2.1 画面撕裂 原因 2.2.2 双缓存 2.2.3 VSync 三.Android屏幕刷新机制 3.1 And ...

  7. Android屏幕渲染

    目录 1 相关知识点 2 渲染机制 2.1 渲染流程 参考文章 1 相关知识点 CPU:中央处理器,它集成了运算.缓冲.控制单元包括绘图功能等.CUP将对象处理为多维图形.纹理(Bitmaps,Dra ...

  8. Android UI 渲染机制的演进,你需要了解什么?

    前言 如今UI 渲染可能是诸多性能问题中最容易被察觉到的,Android 开发既要面对各式各样的手机屏幕尺寸和分辨率,还要与"凶残"的产品和 UI 设计师过招. 在正确实现复杂.炫 ...

  9. 【屏幕刷新】Android 屏幕刷新机制

    显示系统基础知识 在一个典型的显示系统中,一般包括CPU.GPU.Display三个部分, CPU负责计算帧数据,把计算好的数据交给GPU, GPU会对图形数据进行渲染,渲染好后放到buffer(图像 ...

最新文章

  1. Windows、WSL 与 Linux 的性能对比
  2. 第七周项目一-三个函数在一个程序中(5)
  3. 项目管理(一)计时计件
  4. Visual Studio 2010 Ultimate开发与测试敏捷特性
  5. 糖尿病(消渴)的中药简见简方(转载)
  6. 初学者学python,列表推导到zip()函数,必须会的五种技巧
  7. ArrayList(Map(k v))相关操作和遍历
  8. ES6学习笔记六(新增数据结构)
  9. C#验证字符串是否是数字,是否包含中文,是否是邮箱格式,是否是电话格式
  10. matlab x~=0
  11. 深入了解PowerManagerService(一)之Android 11.0 Power 键亮屏灭屏流程分析
  12. m3云服务器_“中国球迷”索尼A7RM3及镜头下的情况肖像
  13. html各种弹出框和提示框
  14. Android studio 启动模拟器出现 VT-x is disabled in BIOS 以及 /dev/kvm is not found
  15. oss 单机游戏云存档
  16. sysbench 压测 安装
  17. 驱动开发:内核封装WSK网络通信接口
  18. SAP ABAP PA certification 培训笔记 part 4
  19. mysql触发器任务
  20. ddos防火墙防御假人***测评

热门文章

  1. STM32-NUCLEO-F411RE-USART_串口
  2. 天津理工大学计算机网络复习
  3. 如何做增值电信业务经营许可证备案
  4. 无需CORS,用nginx解决跨域问题,轻松实现低代码开发的前后端分离
  5. 代码审计-php代码执行
  6. 论文解读:ResNet50
  7. 【ParaView教程】第三章 实战练习 —— 手机跌落
  8. 网络测试视频分析软件,移动端用研测试工具推荐一: Userlytics
  9. ENVI国产卫星插件更新后GF1 PMS传感器辐射定标仍然报错的解决方法
  10. python从网址爬图片协程_Python爬虫多任务协程爬取虎牙MM图片