Android视图SurfaceView的实现原理分析

  次阅读 来源:互联网(转载协议) 2015-10-13 07:43 我要评论(0)

Android系统中,有一种特殊的视图,称为SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面。由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行行绘制。又由于不占用主线程资源,SurfaceView一方面可以实现复杂而高效的UI,另一方面又不会导致用户输入得不到及时响应。在本文中,我们就详细分析SurfaceView的实现原理。

老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!

在前面Android控件TextView的实现原理分析一文中提到,普通的Android控件,例如TextView、Button和CheckBox等,它们都是将自己的UI绘制在宿主窗口的绘图表面之上,这意味着它们的UI是在应用程序的主线程中进行绘制的。由于应用程序的主线程除了要绘制UI之外,还需要及时地响应用户输入,否则的话,系统就会认为应用程序没有响应了,因此就会弹出一个ANR对话框出来。对于一些游戏画面,或者摄像头预览、视频播放来说,它们的UI都比较复杂,而且要求能够进行高效的绘制,因此,它们的UI就不适合在应用程序的主线程中进行绘制。这时候就必须要给那些需要复杂而高效UI的视图生成一个独立的绘图表面,以及使用一个独立的线程来绘制这些视图的UI。

在前面Android应用程序与SurfaceFlinger服务的关系概述和学习计划和Android系统Surface机制的SurfaceFlinger服务简要介绍和学习计划这两个系统的文章中,我们主要分析了Android应用程序窗口是如何通过SurfaceFlinger服务来绘制自己的UI的。一般来说,每一个窗口在SurfaceFlinger服务中都对应有一个Layer,用来描述它的绘图表面。对于那些具有SurfaceView的窗口来说,每一个SurfaceView在SurfaceFlinger服务中还对应有一个独立的Layer或者LayerBuffer,用来单独描述它的绘图表面,以区别于它的宿主窗口的绘图表面。

无论是LayerBuffer,还是Layer,它们都是以LayerBase为基类的,也就是说,SurfaceFlinger服务把所有的LayerBuffer和Layer都抽象为LayerBase,因此就可以用统一的流程来绘制和合成它们的UI。由于LayerBuffer的绘制和合成与Layer的绘制和合成是类似的,因此本文不打算对LayerBuffer的绘制和合成操作进行分析。需要深入理解LayerBuffer的绘制和合成操作的,可以参考Android应用程序与SurfaceFlinger服务的关系概述和学习计划和Android系统Surface机制的SurfaceFlinger服务简要介绍和学习计划这两个系统的文章。

为了接下来可以方便地描述SurfaceView的实现原理分析,我们假设在一个Activity窗口的视图结构中,除了有一个DecorView顶层视图之外,还有两个TextView控件,以及一个SurfaceView视图,这样该Activity窗口在SurfaceFlinger服务中就对应有两个Layer或者一个Layer的一个LayerBuffer,如图1所示:

图1 SurfaceView及其宿主Activity窗口的绘图表面示意图

在图1中,Activity窗口的顶层视图DecorView及其两个TextView控件的UI都是绘制在SurfaceFlinger服务中的同一个Layer上面的,而SurfaceView的UI是绘制在SurfaceFlinger服务中的另外一个Layer或者LayerBuffer上的。

注意,用来描述SurfaceView的Layer或者LayerBuffer的Z轴位置是小于用来其宿主Activity窗口的Layer的Z轴位置的,但是前者会在后者的上面挖一个“洞”出来,以便它的UI可以对用户可见。实际上,SurfaceView在其宿主Activity窗口上所挖的“洞”只不过是在其宿主Activity窗口上设置了一块透明区域。

从总体上描述了SurfaceView的大致实现原理之后,接下来我们就详细分析它的具体实现过程,包括它的绘图表面的创建过程、在宿主窗口上面进行挖洞的过程,以及绘制过程。

1. SurfaceView的绘图表面的创建过程

由于SurfaceView具有独立的绘图表面,因此,在它的UI内容可以绘制之前,我们首先要将它的绘图表面创建出来。尽管SurfaceView不与它的宿主窗口共享同一个绘图表面,但是它仍然是属于宿主窗口的视图结构的一个结点的,也就是说,SurfaceView仍然是会参与到宿主窗口的某些执行流程中去。

从前面Android应用程序窗口(Activity)的绘图表面(Surface)的创建过程分析一文可以知道,每当一个窗口需要刷新UI时,就会调用ViewRoot类的成员函数performTraversals。ViewRoot类的成员函数performTraversals在执行的过程中,如果发现当前窗口的绘图表面还没有创建,或者发现当前窗口的绘图表面已经失效了,那么就会请求WindowManagerService服务创建一个新的绘图表面,同时,它还会通过一系列的回调函数来让嵌入在窗口里面的SurfaceView有机会创建自己的绘图表面。

接下来,我们就从ViewRoot类的成员函数performTraversals开始,分析SurfaceView的绘图表面的创建过程,如图2所示:

图2 SurfaceView的绘图表面的创建过程

这个过程可以分为8个步骤,接下来我们就详细分析每一个步骤。

Step 1. ViewRoot.performTraversals

[java]

public final class ViewRoot extends Handler implements ViewParent,

View.AttachInfo.Callbacks {

......

private void performTraversals() {

// cache mView since it is used so much below...

final View host = mView;

......

final View.AttachInfo attachInfo = mAttachInfo;

本站部分文章来源于网络以及网友投稿,本站只负责对文章进行整理、排版、编辑,是出于传递更多信息之目的,并不意味着赞同其观点或证实其内容的真实性。如果您有什么意见或建议,请联系QQ28-1688-302!

人工智能实验室
相关文章相关文章
  • Oculus公布原型机,大幅度提升可视角,能实现140°的视场水平

    Oculus公布原型机,大幅度提升可视角,能实现140°的视场水平

  • teamLab创始人猪子寿之: 抛去衣食住行,我还剩下什么?

    teamLab创始人猪子寿之: 抛去衣食住行,我还剩下什么?

  • 2018深圳国际人工智能展览会 2018 shenzhen International Artif

    2018深圳国际人工智能展览会 2018 shenzhen International Artif

  • Michael I. Jordan带你解读百万奖金ATEC蚂蚁人工智能大赛

    Michael I. Jordan带你解读百万奖金ATEC蚂蚁人工智能大赛

网友点评网友点评
阅读推荐阅读推荐

据外媒报道,STEER打造了首款完全自动驾驶停车技术,旨在使常规车辆转变为无人驾驶车辆。STEER的首款技术应用是4级自动驾驶及网络安全停车...

近日,美国软性机器抓手制造商 Soft Robotics 宣布,获得 2000 万美元的融资,本轮投资者包括 Scale Venture Partners,Calibrate Ventures...

据外媒报道,加州车管局发布了《2017自动驾驶脱离报告(California Autonomous Vehicle Disengagement Reports)》,其中谈及了脱离的具体...

用人机语音交互,来解决智能家居适老的问题;通过家庭门禁与安防套件、空气净化套件、可燃气体与有害气体监控套件等相互联动,在不同生活情...