前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >走进SurfaceView

走进SurfaceView

作者头像
蜻蜓队长
发布2018-08-03 15:15:43
1.2K0
发布2018-08-03 15:15:43
举报
文章被收录于专栏:Android机动车Android机动车

作者:康白

博客:http://blog.csdn.net/k_bb_666

最近在写视频播放器的时候用到了SurfaceView和MediaPlayer,在各个功能完成后,竟得意忘形,感觉自己又get到新技能,可以嘚瑟几天了,直到前两天被人问到:

问“SurfaceView和Surface有什么区别啊?它们是一个东西吗?” 答“当然不是啊,肯定不是啊…SurfaceView就是一个View啊…Surface是…” …… 紧接着脑海里就响起了我五月天的那首歌…“最怕空气突然安静…” 真是大写的尴尬啊,我想,是时候好好研究一下SurfaceView,顺便总结总结了!

01

Surface是什么

Surface就是“表面”的意思。在SDK的文档中,对Surface的描述是这样的:“Handle onto a raw buffer that is being managed by the screen compositor”,翻译成中文就是“由屏幕显示内容合成器(screen compositor)所管理的原生缓冲器的句柄”,这句话包括下面两个意思:

  1. 通过Surface(因为Surface是句柄)就可以获得原生缓冲器以及其中的内容。就像在C语言中,可以通过一个文件的句柄,就可以获得文件的内容一样;
  2. 原生缓冲器(rawbuffer)是用于保存当前窗口的像素数据的。

引伸地,可以认为Android中的Surface就是一个用来画图形(graphics)或图像(image)的地方。根据Java方面的常规知识,我们知道通常画图是在一个Canvas对象上面进行的,由此,可以推知一个Surface对象中应该包含有一个Canvas对象

02

SurfaceView是什么

SurfaceView是View的派生类,因此它本质上是一个View。但与普通View不同的是,它有自己的Surface ,在WMS中有对应的WindowState,在SurfaceFlinger中有Layer。但只有通过SurfaceView才可以看到Surface的部分或者全部的内容。

我们知道,一般的Activity包含的多个View会组成View hierachy的树形结构,只有最顶层的DecorView,也就是根结点视图,才是对WMS可见的。这个DecorView在WMS中有一个对应的WindowState。相应地,在SurfaceFlinger中对应的Layer。

而SurfaceView自带一个Surface,这个Surface在WMS中有自己对应的WindowState,在SurfaceFlinger中也会有自己的Layer。虽然在App端它仍在View hierachy中,但在Server端(WMS和SurfaceFlinger)中,它与宿主窗口是分离的。这样的好处是对这个Surface的渲染可以放到单独线程去做,渲染时可以有自己的GL context。这对于一些游戏、视频等性能相关的应用非常有益,因为它不会影响主线程对事件的响应。

但它也有缺点,因为这个Surface不在View hierachy中,它的显示也不受View的属性控制,所以不能进行平移,缩放等变换,也不能放在其它ViewGroup中,一些View中的特性也无法使用。在Android中Surface是从Object派生而来,且实现了Parcelable接口。看到Parcelable就让人能很自然地想到数据容器,SurfaceView就是用来展示Surface中的数据的。在这个层面上而言,Surface就是管理数据的地方,SurfaceView就是展示数据的地方。

03

SurfaceHolder

SurfaceHolder是一个接口,其作用就像一个关于Surface的监听器。提供访问和控制SurfaceView背后的Surface 相关的方法 (providing access and control over this SurfaceView’s underlying surface),它通过三个回调方法,让我们可以感知到Surface的创建、销毁或者改变。在SurfaceView中有一个方法getHolder,可以很方便地获得SurfaceView所对应的Surface所对应的SurfaceHolder。

除下面将要提到的SurfaceHolder.Callback外,SurfaceHolder还提供了很多重要的方法,其中最重要的就是:

  1. abstract void addCallback(SurfaceHolder.Callbackcallback) 为SurfaceHolder添加一个SurfaceHolder.Callback回调接口。
  2. abstract Canvas lockCanvas() 获取一个Canvas对象,并锁定之。所得到的Canvas对象,其实就是Surface中一个成员。
  3. abstract Canvas lockCanvas(Rectdirty) 同上。但只锁定dirty所指定的矩形区域,因此效率更高。
  4. abstract void unlockCanvasAndPost(Canvascanvas) 当修改Surface中的数据完成后,释放同步锁,并提交改变,然后将新的数据进行展示,同时Surface中相关数据会被丢失。
  5. public abstract void setType (int type) 设置Surface的类型,接收如下的参数: SURFACE_TYPE_NORMAL:用RAM缓存原生数据的普通Surface SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access )引擎和硬件加速的Surface SURFACE_TYPE_GPU:适用于GPU加速的Surface SURFACE_TYPE_PUSH_BUFFERS:表明该Surface不包含原生数据,Surface用到的数据由其他对象提供,在Camera图像预览中就使用该类型的Surface,有Camera负责提供给预览Surface数据,这样图像预览会比较流畅。如果设置这种类型则就不能调用lockCanvas来获取Canvas对象了。需要注意的是,在高版本的Android SDK中,setType这个方法已经被depreciated了。

2、3、4中的同步锁机制的目的,就是为了在绘制的过程中,Surface中的数据不会被改变。

04

SurfaceHolder.Callback

前面已经讲到SurfaceHolder是一个接口,它通过回调方法的方式,让我们可以感知到Surface的创建、销毁或者改变。其实这一点是通过其内部的静态子接口SurfaceHolder.Callback来实现的。SurfaceHolder.Callback中定义了三个接口方法:

  1. abstract void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 当surface发生任何结构性的变化时(格式或者大小),该方法就会被立即调用。
  2. abstract void surfaceCreated(SurfaceHolder holder) 当surface对象创建后,该方法就会被立即调用。
  3. abstract void surfaceDestroyed(SurfaceHolder holder) 当surface对象在将要销毁前,该方法会被立即调用。

05

它们之间的关系

从设计模式的高度来看,Surface、SurfaceView和SurfaceHolder实质上就是广为人知的MVC,即Model-View-Controller。Model就是模型的意思,或者说是数据模型,或者更简单地说就是数据,也就是这里的Surface;View即视图,代表用户交互界面,也就是这里的SurfaceView;SurfaceHolder很明显可以理解为MVC中的Controller(控制器)。而SurfaceHolder.Callback是SurfaceHolder内部的静态子接口

06

SurfaceView的优缺点

1、优点: 可以在一个独立的线程中进行界面绘制,不会影响主线程,使用双缓冲机制,播放视频时画面更流畅。SurfaceView内部自己持有surface,surface 创建、销毁、大小改变是系统来处理的,通过surfaceHolder 的callback回调通知。当画布创建好时,可以将surface绑定到MediaPlayer中。SurfaceView如果为用户可见的时候,创建SurfaceView的SurfaceHolder用于显示视频流解析的帧图片,如果发现SurfaceView变为用户不可见的时候,则立即销毁SurfaceView的SurfaceHolder,以达到节约系统资源的目的

2、缺点: Surface不在View hierachy中,它的显示也不受View的属性控制,所以不能进行平移,缩放等变换,也不能放在其它ViewGroup中。SurfaceView 不能嵌套使用。

07

SurfaceView双缓冲

双缓冲:在运用时可以理解为:SurfaceView在更新视图时用到了两张Canvas,一张frontCanvas和一张backCanvas,每次实际显示的是frontCanvas,backCanvas存储的是上一次更改前的视图,当使用lockCanvas()获取画布时,得到的实际上是backCanvas而不是正在显示的frontCanvas,之后你在获取到的backCanvas上绘制新视图,再unlockCanvasAndPost(canvas)此视图,那么上传的这张canvas将替换原来的frontCanvas作为新的frontCanvas,原来的frontCanvas将切换到后台作为backCanvas。例如,如果你已经先后两次绘制了视图A和B,那么你再调用lockCanvas()获取视图,获得的将是A而不是正在显示的B,之后你将重绘的C视图上传,那么C将取代B作为新的frontCanvas显示在SurfaceView上,原来的B则转换为backCanvas。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-09-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android机动车 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档