Android 显示原理简介

最新推荐文章于 2025-04-23 14:07:46 发布
十化 最新推荐文章于 2025-04-23 14:07:46 发布
阅读量509 收藏
点赞数
分类专栏: android
android 专栏收录该内容
15 篇文章
订阅专栏
转载自:http://djt.qq.com/article/view/987

现在越来越多的应用开始重视流畅度方面的测试,了解Android应用程序是如何在屏幕上显示的则是基础中的基础,就让我们一起看看小小屏幕中大大的学问。这也是我下篇文章——《Android应用流畅度测试分析》的基础。

 

    首先,用一句话来概括一下Android应用程序显示的过程:Android应用程序调用SurfaceFlinger服务把经过测量、布局和绘制后的Surface渲染到显示屏幕上。

 

名词解释

SurfaceFlinger:Android系统服务,负责管理Android系统的帧缓冲区,即显示屏幕。

Surface:Android应用的每个窗口对应一个画布(Canvas),即Surface,可以理解为Android应用程序的一个窗口。

 

    Android应用程序的显示过程包含了两个部分(应用侧绘制、系统侧渲染)、两个机制(进程间通讯机制、显示刷新机制),接下来我们就来一一道来。

 

应用侧

一个Android应用程序窗口里面包含了很多UI元素,这些UI元素是以树形结构来组织的,即它们存在着父子关系,其中,子UI元素位于父UI元素里面,如下图:

 

 

因此,在绘制一个Android应用程序窗口的UI之前,我们首先要确定它里面的各个子UI元素在父UI元素里面的大小以及位置。确定各个子UI元素在父UI元素里面的大小以及位置的过程又称为测量过程和布局过程。因此,Android应用程序窗口的UI渲染过程可以分为测量、布局和绘制三个阶段。如下图所示:

测量:递归(深度优先)确定所有视图的大小(高、宽)

    布局:递归(深度优先)确定所有视图的位置(左上角坐标)

    绘制:在画布canvas上绘制应用程序窗口所有的视图

 

测量、布局没有太多要说的,这里要着重说一下绘制。Android目前有两种绘制模型:基于软件的绘制模型和硬件加速的绘制模型(从Android 3.0开始全面支持)。

 

    在基于软件的绘制模型下,CPU主导绘图,视图按照两个步骤绘制:

1.      让View层次结构失效

2.      绘制View层次结构

    当应用程序需要更新它的部分UI时,都会调用内容发生改变的View对象的invalidate()方法。无效(invalidation)消息请求会在View对象层次结构中传递,以便计算出需要重绘的屏幕区域(脏区)。然后,Android系统会在View层次结构中绘制所有的跟脏区相交的区域。不幸的是,这种方法有两个缺点:

1.      绘制了不需要重绘的视图(与脏区域相交的区域)

2.      掩盖了一些应用的bug(由于会重绘与脏区域相交的区域)

    注意:在View对象的属性发生变化时,如背景色或TextView对象中的文本等,Android系统会自动的调用该View对象的invalidate()方法。

 

    在基于硬件加速的绘制模式下,GPU主导绘图,绘制按照三个步骤绘制:

1.      让View层次结构失效

2.      记录、更新显示列表

3.      绘制显示列表

这种模式下,Android系统依然会使用invalidate()方法和draw()方法来请求屏幕更新和展现View对象。但Android系统并不是立即执行绘制命令,而是首先把这些View的绘制函数作为绘制指令记录一个显示列表中,然后再读取显示列表中的绘制指令调用OpenGL相关函数完成实际绘制。另一个优化是,Android系统只需要针对由invalidate()方法调用所标记的View对象的脏区进行记录和更新显示列表。没有失效的View对象则能重放先前显示列表记录的绘制指令来进行简单的重绘工作。

使用显示列表的目的是,把视图的各种绘制函数翻译成绘制指令保存起来,对于没有发生改变的视图把原先保存的操作指令重新读取出来重放一次就可以了,提高了视图的显示速度。而对于需要重绘的View,则更新显示列表,以便下次重用,然后再调用OpenGL完成绘制。

硬件加速提高了Android系统显示和刷新的速度,但它也不是万能的,它有三个缺陷:

1.      兼容性(部分绘制函数不支持或不完全硬件加速,参见文章尾)

2.      内存消耗(OpenGL API调用就会占用8MB,而实际上会占用更多内存)

3.      电量消耗(GPU耗电)

 

系统侧

    Android应用程序在图形缓冲区中绘制好View层次结构后,这个图形缓冲区会被交给SurfaceFlinger服务,而SurfaceFlinger服务再使用OpenGL图形库API来将这个图形缓冲区渲染到硬件帧缓冲区中。

 

    由于Android应用程序很少能涉及到Android系统底层,所以SurfaceFlinger服务的执行过程不做过多的介绍。

 

进程间通讯机制

    Android应用程序为了能够将自己的UI绘制在系统的帧缓冲区上,它们就必须要与SurfaceFlinger服务进行通信,如图所示:

Android应用程序与SurfaceFlinger服务是运行在不同的进程中的,因此,它们采用某种进程间通信机制来进行通信。由于Android应用程序在通知SurfaceFlinger服务来绘制自己的UI的时候,需要将UI数据传递给SurfaceFlinger服务,例如,要绘制UI的区域、位置等信息。一个Android应用程序可能会有很多个窗口,而每一个窗口都有自己的UI数据,因此,Android系统的匿名共享内存机制就派上用场了。

每一个Android应用程序与SurfaceFlinger服务之间,都会通过一块匿名共享内存来传递UI数据,如下所示:

 

 

但是单纯的匿名共享内存在传递多个窗口数据时缺乏有效的管理,所以匿名共享内存就被抽象为一个更上流的数据结构SharedClient,如下图所示:

 

在每个SharedClient中,最多有31个SharedBufferStack,每个SharedBufferStack都对应一个Surface,即一个窗口。这样,我们就可以知道为什么每一个SharedClient里面包含的是一系列SharedBufferStack而不是单个SharedBufferStack:一个SharedClient对应一个Android应用程序,而一个Android应用程序可能包含有多个窗口,即Surface。从这里也可以看出,一个Android应用程序至多可以包含31个窗口。

每个SharedBufferStack中又包含了N个缓冲区(<4.1 N=2; >=4.1 N=3),即显示刷新机制中即将提到的双缓冲和三重缓冲技术。

显示刷新机制

    一般我们在绘制UI的时候,都会采用一种称为“双缓冲”的技术。双缓冲意味着要使用两个缓冲区(SharedBufferStack中),其中一个称为Front Buffer,另外一个称为Back Buffer。UI总是先在Back Buffer中绘制,然后再和Front Buffer交换,渲染到显示设备中。理想情况下,这样一个刷新会在16ms内完成(60FPS),下图就是描述的这样一个刷新过程(Display处理前Front Buffer,CPU、GPU处理Back Buffer。

 

 

但现实情况并非这么理想。

1.      时间从0开始,进入第一个16ms:Display显示第0帧,CPU处理完第一帧后,GPU紧接其后处理继续第一帧。三者互不干扰,一切正常。

2.      时间进入第二个16ms:因为早在上一个16ms时间内,第1帧已经由CPU,GPU处理完毕。故Display可以直接显示第1帧。显示没有问题。但在本16ms期间,CPU和GPU却并未及时去绘制第2帧数据(注意前面的空白区),而是在本周期快结束时,CPU/GPU才去处理第2帧数据。

3.      时间进入第3个16ms,此时Display应该显示第2帧数据,但由于CPU和GPU还没有处理完第2帧数据,故Display只能继续显示第一帧的数据,结果使得第1帧多画了一次(对应时间段上标注了一个Jank)。

    通过上述分析可知,此处发生Jank的关键问题在于,为何第1个16ms段内,CPU/GPU没有及时处理第2帧数据?原因很简单,CPU可能是在忙别的事情,不知道该到处理UI绘制的时间了。可CPU一旦想起来要去处理第2帧数据,时间又错过了!

 

    为解决这个问题,Android 4.1中引入了VSYNC,这类似于时钟中断。结果如下图所示:

 

由上图可知,每收到VSYNC中断,CPU就开始处理各帧数据。整个过程非常完美。

    不过,仔细琢磨后却会发现一个新问题:上图中,CPU和GPU处理数据的速度似乎都能在16ms内完成,而且还有时间空余,也就是说,CPU/GPU的FPS(帧率,Frames Per Second)要高于Display的FPS。确实如此。由于CPU/GPU只在收到VSYNC时才开始数据处理,故它们的FPS被拉低到与Display的FPS相同。但这种处理并没有什么问题,因为Android设备的Display FPS一般是60,其对应的显示效果非常平滑。

    如果CPU/GPU的FPS小于Display的FPS,会是什么情况呢?请看下图:

 

由上图可知:

1.      在第二个16ms时间段,Display本应显示B帧,但却因为GPU还在处理B帧,导致A帧被重复显示。

2.      同理,在第二个16ms时间段内,CPU无所事事,因为A Buffer被Display在使用。B Buffer被GPU在使用。注意,一旦过了VSYNC时间点,CPU就不能被触发以处理绘制工作了。

    为什么CPU不能在第二个16ms处开始绘制工作呢?原因就是只有两个Buffer(Android 4.1之前)。如果有第三个Buffer的存在,CPU就能直接使用它,而不至于空闲。出于这一思路就引出了三重缓冲区(Android 4.1)。结果如下图所示:

由上图可知:

第二个16ms时间段,CPU使用C Buffer绘图。虽然还是会多显示A帧一次,但后续显示就比较顺畅了。

是不是Buffer越多越好呢?回答是否定的。由上图可知,在第二个时间段内,CPU绘制的第C帧数据要到第四个16ms才能显示,这比双Buffer情况多了16ms延迟。所以,Buffer最好还是两个,三个足矣。

到这里,Android系统的显示原理就介绍完了。那么在了解这些原理后对我们的流畅度测试有哪些帮助呢,请看我的下篇文章《Android应用流畅度测试分析》。

 

 

附:不同的API Level下,绘制函数对硬件加速模式的支持情况

 

确定要放弃本次机会?
福利倒计时
: :

立减 ¥

普通VIP年卡可用
立即使用
十化
关注 关注
  • 0
    点赞
  • 踩
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
  • 分享
    复制链接
    分享到 QQ
    分享到新浪微博
    扫一扫
  • 举报
    举报
专栏目录
Android系统显示原理
ssdk_boy的博客
12-17 544
一.Android系统显示原理 Android的显示过程简单概括为:Android 应用程序把经过测量、布局、绘制后的surface缓存数据,通过surfaceFlinger把数据渲染到显示屏幕上,通过Android的刷新机制来刷新数据。也就是说应用层负责绘制,系统层负责渲染,通过进程间通信把应用层需要绘制的数据传递给系统层服务,系统层服务通过刷新机智把数据刷新到屏幕。 通过阅读Android...
掌握Android图像显示原理(上)
子者不语的专栏
09-06 8009
我们所知道的Activity或者是应用App界面的显示,只属于Android图形显示的一部分。同样可以在Android系统上展示图像的WebView,Flutter,或者是通过Unity开发的3D游戏,他们的界面又是如何被绘制和显现出来的呢?他们和我们所熟悉的Acitvity的界面显示又有什么异同点呢?我们可以不借助Activity的setView或者InflateView机制来实现在屏幕上显示出我们想要的界面吗?Android系统显示界面的方式又和IOS,或者Windows等系统有什么区别呢?
参与评论 您还未登录,请先 登录 后发表或查看评论
Android显示原理
分享Android开发知识
05-08 525
一、概要 Android应用程序显示的过程:Android应用程序调用SurfaceFlinger服务把经过测量、布局和绘制后的Surface渲染到显示屏幕上。 SurfaceFlinger:android系统服务,负责管理android系统的帧缓冲区,即显示屏幕。 Surface:android应用的每个窗口对应一个画布(Canvas),即Surface,可以理解为android应用程序的一个窗口。 Android应用程序的显示过程包含了两个部分(应用侧绘制、系统侧渲染)、两个机制(进程间通讯机制、显
Android三级缓存原理讲解
01-06
三级缓存 内存缓存 本地缓存(SD卡缓存) 网络缓存 ...网络缓存顾名思义就是从网络获取图片资源,然后来进行显示,那么我们可以通过AsyncTask来异步处理网络请求,然后主线程设置图片。 本地缓存 当从网
Android Telephony原理解析与开发指南_杨青平.zip
06-12
总结一下,Android Telephony原理解析与开发指南将详细介绍以下几个方面: 1. Dialer与Telecom之间的通信流程,包括拨打、接听、挂断电话的操作。 2. Telecom如何管理电话会话,以及如何调度不同的电话服务。 3. ...
STM32F103C8T6单片机便携式数字示波器电路pdf原理图STM32控制Android显示源代码和文档资料.zip
02-26
基于Android显示的便携式数字示波器设计文档可能是项目的设计报告或者用户手册,其中涵盖了系统架构、软件设计、功能实现、性能评估等重要内容。这份文档可能还会讨论如何在Android平台上开发相应的应用程序,包括...
flutter和android原生 界面显示的原理是什么,有什么异同。
呆咖啡的博客
09-05 1661
Flutter 和 Android 原生的界面显示原理在底层实现上有很大的不同,尽管它们都是用于构建移动应用的 UI 框架。理解这两者的显示原理,可以帮助开发者更好地优化界面性能并选择合适的技术栈。下面将从底层原理和具体步骤详细说明两者的异同。
Android View的工作原理详解
10-24
详细讲解Android View的工作原理。分析源码,讲解View的工作流程,何时开始触发等等。
Android小知识-了解下Android系统的显示原理
weixin_34242331的博客
10-19 134
本平台的文章更新会有延迟,大家可以关注微信公众号-顾林海,包括年底前会更新kotlin由浅入深系列教程,目前计划在微信公众号进行首发,如果大家想获取最新教程,请关注微信公众 在Android系统中应用层负责绘制,系统层负责渲染,通过进程间通信把应用层需要绘制的数据传递到系统层,系统层服务通过刷新机制把数据更新到屏幕上,图形显示系统采用的是C/S架构。 Android中View绘制需要三个步骤,...
Android系统显示原理【转载】
qq_42111674的博客
08-14 562
原文作者为:斜杠Allen 原文地址为:https://www.jianshu.com/p/9755da0f4e8f Android 显示过程可以简单概括为:Android 应用程序把经过测量、布局、绘制后的 surface 缓存数据,通过 SurfaceFlinger 把数据渲染到显示屏幕上, 通过 Android 的刷新机制来刷新数据。也就是说应用层负责绘制,系统层负责渲染,通过进程间通信...
Android中Activity显示原理
最新发布
qq_45906596的博客
04-23 732
抽象类的唯一实现类,代表一个应用窗口(如 Activity 的窗口),负责管理窗口的视觉元素(标题栏、背景等)和视图层级结构。维护所有窗口的 Z-Order(如 Activity、Dialog、Toast 的显示顺序)。理解此流程可优化 UI 性能(如减少布局层级)和解决窗口显示问题(如动画卡顿)。的测量(measure)、布局(layout)、绘制(draw)。(Binder 代理)与 WMS 通信,完成窗口的添加、更新、删除。(FrameLayout 的子类),并加载窗口默认布局(如。
Android显示原理源码分析
笔沫拾光
03-05 1927
在博文DecorView绘制流程源码分析中,我们对Android的显示原理简单的说了一下,但没有深入。在博文中我们只知道Choreographer(舞蹈指挥者)只是post了一个操作,但后面到底怎么执行的?按啥逻辑执行的?我们都不清楚,作为一个喜欢刨根问底的程序员,是必须要分析分析的。 在开始分析之前,我们需要了解一些概念,如: ViewRootImpl:是View的绘制的辅助类,所有Vie...
Android 渲染机制——原理篇(显示原理全过程解析)
热门推荐
卜大爷的博客
12-09 4万+
帧率 每秒的帧数(fps)或者说帧率是以帧为单位的位图图像每秒连续出现在显示器上的次数(速率)。简单来说就是一秒钟,屏幕显示多少张画面。 为什么是 60fps ? 人类视觉的时间敏感度和分辨率根据视觉刺激的类型和特征而变化,并且在个体之间不同。人类视觉系统每秒可处理10到12个图像并单独感知它们,而较高的速率则被视为运动。12fps 大概类似手动快速翻动书籍的帧率,这明显是可以感知到不够顺滑的。24fps 使得人眼感知的是连续线性的运动,这其实是归功于运动模糊的效果。24fps 是电影胶圈通常使用的帧率,
Android系统开发 ----- 屏幕展示图像原理
weixin_68948960的博客
07-26 1744
日常Android应用开发过程中,没有去了解Android的组件,Activity、Dialog等等可以设置xml布局文件或者可以直接设置控件对象到界面上。哪么真正从设置控件到展示在屏幕上的流程和原理,我们认识多少呢?当然日常应用开发不用了解这些,作为知识扩展还是可以了解一下WindowManagerService(WMS)系统服务做什么?SurfaceFlingerNative服务做什么?OpenGLES是什么?FrameBuffer是什么?等等,一系列的概念和名称我们都可以了解到。...
Android显示系统详解
dream_caoyun的博客
06-23 4889
一、显示系统的分类: 我们来思考一个问题:从普通用户角度来说,某个APP页面(例如购物APP首页)是怎么被显示到屏幕的? 首先看到的是物理屏幕,然后是屏幕中软件工程师编写的APP页面,也就是手机屏幕驱动+应用APP,能看出来必然要有一个中介将应用APP图像数据传递渲染到屏幕的驱动,投递到硬件屏幕去显示,这就是Android框架的作用,称之为Android显示系统模块。也就是说能分为以下几块: 1、硬件屏幕+驱动(我就知道个汇顶),驱动节点是 /dev/graphics/fb*,(fb0代表第一个moni
十化

博客等级

码龄13年
25
原创
6
点赞
13
收藏
3
粉丝
关注
私信

热门文章

  • VLC详细的使用说明以及配置… 26601
  • qt&nbsp;removeWidget(删除布局内… 7504
  • QT中MainWindow的布局设置 6178
  • ubuntu下编译android vlc出现:possibly undefined macro: AC_PROG_LIBTOOL please use m4_pattern_allow 4170
  • 导入android-support-v7-appcompat出现问题: android:Widget.Material.ActionButton 3344

分类专栏

  • java
  • android importandroid-support-v7-appcompat
    1篇
  • 链接地址
    2篇
  • android vlc
    1篇
  • git@osc
  • android
    15篇
  • qt
    8篇
  • windows
    3篇
  • 线程进程
    1篇
  • cocos2dx
    1篇

展开全部 收起

最新评论

  • qt&nbsp;removeWidget(删除布局内…

    Tisfy: 写得太好了!正如那:故国神游,多情应笑我,早生华发。

  • VLC详细的使用说明以及配置…

    u012804784: 棒棒的,话说上面这些面试题,2年工作经验都这么难么,平时工作996业务开发根本涉及不到其中的1‰

  • qt控件注册与反注册及初始化和脚本…

    FNR_S: 您好!请问一下key代表啥意思

  • VLC详细的使用说明以及配置…

    爱吃豆芽的老魏: 我在实际操作中遇到一个问题: 在使用chrome 44版本浏览器时,电脑系统是64位的用32位vlc是正常的。但换个32位的电脑,在谷歌里就却找不到vlc插件。更别提播放了,您能指导下吗

  • 导入android-support-v7-appcompat出现问题: android:Widget.Material.ActionButton

    十化 回复 公瑾道人: 很高兴对你有所帮助

最新文章

  • 关于android:configChanges的属性
  • android提高进程优先级的若干方法
  • 文章链接
2016年2篇
2015年9篇
2014年26篇

目录

展开全部

收起

相关专栏

Android●知识点与疑难

专栏

6 人学习

Android相关知识以及题目,以实际面试为线索,逐步深入整理面试题目以及相关知识点。

Android 系统源码定制

专栏

27 人学习

Android 10 ~ Android 15

Android Radio

专栏

90 人学习

本专栏主要是博主在Radio学习和开发过程中的相关笔记,主要以分析源码调用流程为主,同时包含实际开发中遇到的问题及解决方案。其中源码部分主要是 Android 9.0 和 Android 11,有什么问题或者其他需求也可以评论或留言。文章内容会在博主的工作积累中不断更新完善。

目录

展开全部

收起

分类专栏

  • java
  • android importandroid-support-v7-appcompat
    1篇
  • 链接地址
    2篇
  • android vlc
    1篇
  • git@osc
  • android
    15篇
  • qt
    8篇
  • windows
    3篇
  • 线程进程
    1篇
  • cocos2dx
    1篇

展开全部 收起

目录

评论
被折叠的  条评论 为什么被折叠? 到【灌水乐园】发言
查看更多评论
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值