一,写在前面

本篇文章会以图文的方式介绍Android设备的显示原理,不会深入到源码去分析一些细节,阅读本篇文章会对显示原理有个感性的认识,以便更好的理解Android性能优化相关的原理。


二,为什么要学习Android显示原理

大家玩手机上的应用,会经常遇到卡顿的情况。作为应用层的开发者,就需要在应用层尽可能的避免卡顿的发生,提供给用户一个良好的用户体验。一个经常卡顿的App是灾难性的,它会流失一批批忠实的粉丝。在这方面,个人认为微信就是一款非常nice的应用,这款强大的社交软件在经受上亿用户的锤炼下,并没有出现太多卡顿的情况。总体来说,体验很腾讯,用起来很流畅。回到正题,谈到“卡顿”,想必很多开发者并不真正理解what is 卡顿。

那么,什么是卡顿呢?卡顿的本质是出现掉帧。先了解一个概念,FPS,相信玩游戏的哥们对这个并不陌生,它表示每秒传递的帧数。操作应用时,不管是界面内容变化,还是动画的效果等等,都是由一帧一帧的画面组成。

通常Android显示设备的刷新率是60HZ,意味着每一帧要显示出来需要16ms(1000/60)。只要想办法在16ms内完成预计的一帧的画面处理,那么就不会出现卡顿。如果第1帧的画面超过16ms,那么在下一个16ms的周期到来时,由于第1帧的准备工作还没有完成,界面会继续显示第0帧的画面,这个时候就出现了掉帧,而掉帧就会导致卡顿。

如果不理解掉帧为啥导致卡顿,想象一种极限的情况:如果一帧画面的准备工作耗时1小时完成,那么界面上1h内只显示了一帧的画面,是不是就卡得忒夸张了点~

上面的介绍可知,卡顿就是显示出现了问题,因此需要了解Android的显示原理。了解一帧帧画面的数据是哪来的,处理数据的准备工作是怎么完成的,谁在调控16ms显示一帧画面等等相关知识点......


三,Android显示原理

Android显示原理的架构是C/S架构,S是系统层的服务SurfaceFlinger来扮演,它由C++语言编写;C一部分是Java提供给应用层使用的API,一部分是C++编写的底层实现。本篇文章不会从源码角度分析显示原理,有兴趣的哥们可以自行了解。了解Android的显示原理,需要从绘制原理刷新机制进行分析,下面会具体介绍,关于系统层的服务SurfaceFlinger将不再详细阐述。

Android的显示的大致流程:应用层将测量,布局,绘制后的数据给到SurfaceFlinger,SurfaceFlinger会将数据渲染到屏幕上,并配合Android的刷新机制来不断的刷新数据,最终显示出一帧帧的画面。

那么应用层绘制的数据,如何传递到系统层服务SurfaceFlinger的呢?

不同进程之间的通信,采用的肯定是跨进程的通信传输数据。Android采用的是一个叫SharedClient的匿名共享内存,来实现进程间数据的传输,它的底层实现仍是Binder机制。由于不同进程间是直接操作内存,因此匿名共享内存比一般的进程间通信的效率要高。若对匿名共享内存感兴趣,可参考文章匿名共享内存。

Android显示的框架图如下:

一个应用对应一个SharedClient,一个SharedClient包含31个SharedBufferStack,每个SharedBufferStack包含两个缓存区(4.1版本以前)或三个缓存区(4.1版本以后)。每个SharedBufferStack对应一个Window,因此一个应用最多包含31个窗口。关于缓冲区,后面在介绍刷新机制时会介绍它。


四,绘制原理

我们知道View的绘制流程分为三个过程:Measure,Layout,Draw。

一个布局文件的View的层级图,如下所示:

Measure

测量某一个View时,会先测量它的子View的宽高,然后再测量出自己的宽高大小,详情可参考文章View的测量原理。

Layout

设置某一个View的布局时,先确定其相对于父控件左上角的位置,再结合测量过程中得到的宽高数据,最终确定该View在应用程序窗口中的位置。

Draw

Android支持两种绘制方式:软件绘制(CPU)和硬件加速(GPU),其中硬件加速在3.0版本开始全面支持。

硬件加速的优点:在UI的显示和绘制上效率远高于CPU绘制;

硬件加速的缺点:

  1. GPU的功耗比CPU高
  2. 消耗内存更多
  3. 某些API不支持硬件加速

关于View绘制的三大流程的更多介绍,由于不是本篇文章的重点便不具体介绍啦,需要了解的童鞋可以查阅相关资料学习。


五,刷新机制

·通过上面的介绍,Android的显示流程大致分为三个部分:

  1. 应用层完成测量,布局,绘制的过程
  2. 将应用层绘制的数据,存放在匿名共享内存SharedClient中
  3. SurfaceFlinger将缓存中的数据渲染到屏幕上

那么SurfaceFlinger是如何将缓存中的数据,渲染到屏幕上的呢?

首先是CPU准备绘制过程中的数据,数据通过driver交给GPU渲染到屏幕上。这个driver是一个图形驱动,里面维护着一个队列。CPU将显示相关的数据放到队列里,GPU再将队列里的数据取出来,最后在屏幕上进行显示。

前面提到,Android的显示流程需要配合刷新机制,将一帧帧的画面显示在屏幕上。我们知道Android显示设备的FPS是60HZ,如果希望不发生卡顿,那么CPU/GPU需要在16ms内完成1帧的绘制。可以确定的是16ms就是一个周期,在该周期内要完成屏幕要求的一帧的绘制。CPU/GPU每16ms就绘制一帧,它为什么能遵循这个规定了呢


下面咱们先了解几个概念,分别是:双缓冲,三缓冲,VSYNC

在Android4.1之前,Android手机的流畅性方面是比较差的,于是Android团队在Android4.1版本推出了Project Butter。Project Butter在原有显示系统的基础上,添加了三个核心元素:VSYNC,Triple Buffer,Choreographer。

双缓冲:一个是Back Buffer,一个是Front Buffer,两个缓冲均在SharedBufferStack中。当一个Buffer中准备好数据后,通过io_ctrl来通知显示设备切换Buffer。

VSYNC:定时中断。双缓存需要CPU主动查询Buffer中数据是否准备好,才会去刷新屏幕,因此效率比较低。显示系统引入ASYNC之后,只要CPU收到ASYNC信号,就会开始处理一帧帧的数据。

三缓冲:即Triple Buffer。利用CPU/GPU的空闲时间准备数据,用于弥补在VSYNC+双缓冲配合使用的缺陷(下面会具体介绍)

另外,Choreographer起调度作用,在vsync信号到来时,使应用的绘制工作有序进行。


下面以时序图来分析Android显示系统的刷新机制,分为如下四种情况讨论。

1,没有VSYNC信号时

刷新机制的时序图如下:

横坐标表示时间,一个周期16ms为一个格子。纵坐标分别是:CPU,GPU,显示设备。

第1个16ms时间内,CPU,GPU完成了第1帧处理;

第2个16ms时,CPU刚开始并未处理数据,而是在时间快结束时开始处理数据。该时间段内显示第1帧的数据,显示正常;

第3个16ms时,GPU仍在处理第2帧的数据。该时间段内显示第1帧的数据,显示不正常(本该显示第2帧);

我们发现,在没有VSYNC的情况下,CPU不知道什么时候开始处理数据,会出现两帧的时间,显示的一帧的画面。掉帧就会出现一定程度的卡顿,因此在Android4.1版本以后,引入了VSYNC信号来通知CPU处理数据。


2,引入VSYNC信号后

刷新机制的时序图如下:

可以看到,每当VSYNC信号来临时,就会通知CPU开始处理数据。每一帧的数据在16ms内处理完成,就不会出现卡顿现象,当然这是一种理想情况。


3,引入VSYNC信号,某一帧数据在16ms内未完成处理

刷新机制的时序图如下:

第1个16ms时间段里,A Butter由Display使用,CPU处理完了数据,B Buffer给GPU在使用,但GPU并未处理完数据(A,B Buffer就是双缓存的两个缓冲区);

第2个16ms时间段里,当VSYNC信号到来时,由于GPU需要处理前一帧的数据,CPU不再开始处理数据。等GPU处理完第1帧的数据后,CPU由于没有收到VSYNC信号,并不再处理第2帧的数据,等待下一个VSYNC信号的来临。此时,B Buffer由GPU使用,A Buffer由Display使用。屏幕仍显示第1帧时的画面,且cpu处于空闲状态。

那么,如何解决第2个16ms时间段里,当VSYNC信号到来时CPU及时的处理数据呢?答案是:使用Triple Buffer增加一个缓冲区,这就是显示系统新增的三缓冲技术。


4,引入VSYNC信号时,某一帧数据在16ms内未完成处理,使用三缓冲技术

刷新机制的时序图如下:

在第2个16ms的时间段内,尽管GPU仍在处理前一帧的数据,当VSYNC信号到来时CPU就开始处理数据了。在第4个16ms的时间段里显示了C,比正常情况只延迟了16ms。三缓冲相对双缓冲降低了一定的延迟,保持了界面的流畅度。

注意:如果双缓冲可以正常的处理每帧数据,一般不会用到三缓冲。


六,卡顿的原因

卡顿的原因有两种:

  1. 主线程被阻塞,或者说主线程忙于处理其他操作。尽管Android系统的VSYNC信号每16ms就发送一次,但如果在16ms内CPU在做其他事情,并没有去准备UI显示相关的数据。那么依然会出现掉帧,掉帧就会导致卡顿。
  2. 绘制任务太重,绘制一帧的画面耗时高于16ms。本篇文章在多个地方提到:可能在某一帧的时间里,CPU/GPU并未处理完一帧的数据。于是出现掉帧,掉帧就会卡顿。

解决方案

第1种情况:避免在主线程执行耗时操作,以及和UI无关的操作;

第2中情况:优化布局,以及避免过度绘制;

O(∩_∩)O

图文浅析之Android显示原理相关推荐

  1. Android 显示原理简介

    转载文章,原文地址:http://djt.qq.com/article/view/987 作者:yearzhu,2011年进入腾讯公司,从事过Web端及移动端的测试工作,喜爱新鲜事物及新技术,目前在S ...

  2. android view交替动画,Android View原理(View树遍历,View重绘,View动画)

    一.屏幕绘图基础 Android中的GUI系统是客户端和服务端配合的窗口系统,即后台运行了一个绘制服务,每个应用程序都是该服务端的一个客户端,当客户端需要绘制时,首先请求服务端创建一个窗口,然后在窗口 ...

  3. AndroidUI显示原理及性能优化

    昨天看了泓洋大神的一片有关布局优化的文章,发现自己对ui布局显示方面还是非常的菜的,于是决定好好学一下这方面的知识. 首先,学习一下Android显示原理. 安卓显示原理 Android应用程序显示过 ...

  4. Android 的显示原理

    文章目录 相关问题 setContentView 它的原理是什么? Activity 在 onResume() 之后才会显示的原因是什么? 相关问题 Activity 的显示原理 (Window.De ...

  5. 【转】Android Activity原理以及其子类描述,androidactivity

        Android Activity原理以及其子类描述,androidactivity 简介 Activity是Android应用程序组件,实现一个用户交互窗口,我们可以实现布局填充屏幕,也可以实 ...

  6. Android显示系统详解

    一.显示系统的分类: 我们来思考一个问题:从普通用户角度来说,某个APP页面(例如购物APP首页)是怎么被显示到屏幕的? 首先看到的是物理屏幕,然后是屏幕中软件工程师编写的APP页面,也就是手机屏幕驱 ...

  7. Android布局原理与优化

    Android布局原理与优化 目录: 绘制原理 CPU与GPU Android 图形系统的整体架构 RenderThread 硬件加速和软件绘制 invalidate软件绘制流程 invalidate ...

  8. Android内存原理

    Android内存原理不用在意剩余内存的大小.其实很多人都是把使用其他系统的习惯带过来了.安卓Android大多应用没有退出的设计其实是有道理的,这和系统对进程的调度机制有关系.如果你知道java,就 ...

  9. ANR 弹窗的显示原理

    目录 基础知识: 实验: ANR 弹窗的显示原理 思考一个面试题,一个 Service 运行在独立的进程里,在这个 Service 的 onCreate 方法里执行耗时操作会造成 ANR 吗? 直接说 ...

最新文章

  1. org.codehaus.plexus.archiver.jar.Manifest.write(java.io.PrintWriter)
  2. 初步认识Linux oops 消息
  3. 接口结构_适用于Mac系统的API接口调试应用
  4. 【收藏】K8S部署minio对象存储
  5. 网路知识:为什么宽带越用越慢,看完你就明白了
  6. 计算机程序备份,将应用程序快照备份到计算机
  7. 简述java的线程_Java多线程的简述
  8. mybatis plus 插入生成id_早点下班陪女朋友系列之Mybatis-plus代码生成器
  9. 简单就是不复杂 转
  10. 灵悟礼品网上专卖店——前阶段总结
  11. 张量基础学习(四 张量代数运算——下)
  12. 匿名mahony互补滤波代码详解
  13. W3C school
  14. MySQL联合索引以及索引顺序优化
  15. ipv6笔记无状态地址自动配置及状态
  16. 我的世界神奇宝贝服务器注册指令,我的世界神奇宝贝MOD召唤指令汇总攻略
  17. 学计算机的学后感,关于大学生计算机学习心得体会(精选4篇)
  18. 短信验证码原理java_[java发送短信验证码原理]java发送短信验证码
  19. cics 服务端配置_使用PHP在CICS上构建RESTful服务
  20. Linux网络编程 - 多进程服务器端(1)

热门文章

  1. 【微名片集】免费电子名片如何使用
  2. Oracle Advanced Queue (DBMS_AQ/DMBS_AQADM)
  3. JS中this的指向
  4. python类似图片查找_python查找重复图片并删除(图片去重)
  5. 「解析」牛客网-华为机考企业真题 21-40
  6. ISCXTor2016数据集(Tor-nonTor dataset)介绍
  7. cjt意思_cjts的含义,cjts是什么的缩写,cjts的词语,cjts代表的意思
  8. SQLServer学习笔记(二):数据库的操作
  9. 基于WEB的学生考勤管理系统
  10. devc++编译时 devc undefind reference to '_imp_htonl'