Android之SurfaceView

来源:互联网 发布:上海炫踪网络上市 编辑:程序博客网 时间:2024/05/15 05:49

SurfaceView也用过很多了,今天对Android中SurfaceView以及相关知识进行整理总结。


首先,来看一下Android API对SurfaceView的介绍:


Provides a dedicated drawing surface embedded inside of a view hierarchy. You can control the format of this surface and, if you like, its size; the SurfaceView takes care of placing the surface at the correct location on the screen

The surface is Z ordered so that it is behind the window holding its SurfaceView; the SurfaceView punches a hole in its window to allow its surface to be displayed. The view hierarchy will take care of correctly compositing with the Surface any siblings of the SurfaceView that would normally appear on top of it. This can be used to place overlays such as buttons on top of the Surface, though note however that it can have an impact on performance since a full alpha-blended composite will be performed each time the Surface changes.

The transparent region that makes the surface visible is based on the layout positions in the view hierarchy. If the post-layout transform properties are used to draw a sibling view on top of the SurfaceView, the view may not be properly composited with the surface.

Access to the underlying surface is provided via the SurfaceHolder interface, which can be retrieved by callinggetHolder().

The Surface will be created for you while the SurfaceView's window is visible; you should implementsurfaceCreated(SurfaceHolder) andsurfaceDestroyed(SurfaceHolder) to discover when the Surface is created and destroyed as the window is shown and hidden.

One of the purposes of this class is to provide a surface in which a secondary thread can render into the screen. If you are going to use it this way, you need to be aware of some threading semantics:

  • All SurfaceView and SurfaceHolder.Callback methods will be called from the thread running the SurfaceView's window (typically the main thread of the application). They thus need to correctly synchronize with any state that is also touched by the drawing thread.
  • You must ensure that the drawing thread only touches the underlying Surface while it is valid -- betweenSurfaceHolder.Callback.surfaceCreated() andSurfaceHolder.Callback.surfaceDestroyed().  

接下来,说一下自己的理解:

SurfaceView继承View,它的特性是:能够在子线程中刷新UI线程。

如何实现呢?

继承SurfaceView类,并且实现SurfaceHolder.Callback接口

需要重写的方法:

SurfaceView创建时回调

public void surfaceCreated(SurfaceHolder holder){}

Surface的大小发生改变时回调

public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){}

销毁时回调

public void surfaceDestroyed(SurfaceHolder holder) {}


整个处理过程如下:

继承SurfaceView并实现SurfaceHolder.Callback接口--->SurfaceView.getHolder()获得SurfaceHolder对象--->

SurfaceHolder.addCallback(callback)添加回调函数--->SurfaceHolder.lockCanvas()获得Canvas对象并锁定画布

--->Canvas绘画--->SurfaceHolder.unlockCanvasAndPost(Canvas canvas)


这里涉及到一个类SurfaceHolder的,关于SurfaceHolder,

SurfaceHolder 是对 SurfaceView 的 Surface 的包装,不但在 SurfaceHolder.Callback 接口中负责 Surface 创建、大小改变和销毁的回调,而且还对 Surface 的关键方法 LockCanvas()、unLockCanvasAndPost() 方法进行了线程安全的包装,所以 SurfaceHolder 是 Surface 对象的持有者,负责 Surface 的生命周期中对 Surface 操作方法的调用。

SurfaceView、SurfaceHolder、Surface三者的关系如下图:



SurfaceView视图内嵌了一个专门用于绘制的Surface,其实每一个Surface都在每一个窗口的后面,我们可以通过SurfaceView类来控制哪些Surface的内容可以显示出来,其实它的作用就是可以直接从内存或者是DMA硬件里获取图像数据,将这些图像数据迅速地显示出来,通过开启一个渲染线程可以迅速地完成画面的更新。

另外,SurfaceView使用双缓冲机制,使SurfaceView同时对两张图片进行渲染操作,其实目的也是为了迅速更新图片的显示,第一个缓冲对这一帧进行解析,第二个会对下一帧进行解析,这样就可以避免在上一帧的图片显示完成后,下一帧的图片还没有进行显示的情况发生。

surface是纵深排序(Z-ordered)的,可以通过setZOrderOnTop(true)或者setZOrderMediaOverlay(true)来设置。

但是,必须在surface进行渲染前调用,在渲染的过程中调用无效。



我们再来看一下GLSurfaceView、SurfaceTexture、TextureView:

GLSurfaceView:GLSurfaceView是从API level3加上的,它是SurfaceView的子类。在SurfaceView的基础上,它加入了EGL的管理,并自带了渲染线程。另外它定义了用户需要实现的Render接口,提供了用Strategy pattern更改具体Render行动的灵活性。作为GLSurfaceView的Client,只需要将实现了渲染函数的Renderer的实现类设置给GLSurfaceView便可。


SurfaceTexture:SurfaceTexture是从API level11开始引入的。和SurfaceView不同的是,它对图象流的处理其实不直接显示,而是转为GL外部纹理,因此可用于图象流数据的2次处理(如Camera滤镜,桌面殊效等)。比如Camera的预览数据,变成纹理后可以交给GLSurfaceView直接显示,也能够通过SurfaceTexture交给TextureView作为View heirachy中的1个硬件加速层来显示。首先,SurfaceTexture从图象流(来自Camera预览,视频解码,GL绘制场景等)中取得帧数据,当调用updateTexImage()时,根据内容流中最近的图象更新SurfaceTexture对应的GL纹理

对象,接下来,就能够像操作普通GL纹理一样操作它了。


TextureView:TextureView是从API level14开始引入的。可以将内容流直接投影到View中,可以用于实现Live preview等功能。和SurfaceView不同,它不会在WMS中单独创建窗口,而是作为View hierachy中的1个普通View,因此可以和其它普通View一样进行移动,旋转,缩放,动画等变化。值得注意的是TextureView必须在硬件加速的窗口中。它显示的内容流数据可以来自App进程或是远端进程。

1 0