什么是Surface?html
android API的解释是:Handle onto a raw buffer that is being managed by the screen compositorandroid
Surface对应了一块屏幕的缓冲区,每个window对应一个Surface,任何View都是画在Surface上的,传统的view共享一块屏幕缓冲区,全部的绘制都必须在UI线程上进行。编程
什么是SurfaceViewcanvas
SurfaceView的API中文翻译:api
SurfaceView是视图(View)的继承类,这个视图里内嵌了一个专门用于绘制的Surface。你能够控制这个Surface的格式和尺寸。Surfaceview控制这个Surface的绘制位置。
Surface是纵深排序(Z-ordered)的,这代表它总在本身所在窗口的后面。surfaceview提供了一个可见区域,只有在这个可见区域内 的surface部份内容才可见,可见区域外的部分不可见。surface的排版显示受到视图层级关系的影响,它的兄弟视图结点会在顶端显示。这意味者 surface的内容会被它的兄弟视图遮挡,这一特性能够用来放置遮盖物(overlays)(例如,文本和按钮等控件)。注意,若是surface上面 有透明控件,那么它的每次变化都会引发框架从新计算它和顶层控件的透明效果,这会影响性能。
你能够经过SurfaceHolder接口访问这个surface,getHolder()方法能够获得这个接口。
surfaceview变得可见时,surface被建立;surfaceview隐藏前,surface被销毁。这样能节省资源。若是你要查看 surface被建立和销毁的时机,能够重载surfaceCreated(SurfaceHolder)和 surfaceDestroyed(SurfaceHolder)。
surfaceview的核心在于提供了两个线程:UI线程和渲染线程。这里应注意:
1> 全部SurfaceView和SurfaceHolder.Callback的方法都应该在UI线程里调用,通常来讲就是应用程序主线程。渲染线程所要访问的各类变量应该做同步处理。
2> 因为surface可能被销毁,它只在SurfaceHolder.Callback.surfaceCreated()和 SurfaceHolder.Callback.surfaceDestroyed()之间有效,因此要确保渲染线程访问的是合法有效的surface。框架
SurfaceView继承与View每个SurfaceView建立的时候都会建立一个Window将自身与window绑定在一块儿,因此SurfaceView内嵌了一个本身的Surface,传统的view以及派生类的更新只能在UI线程,而后UI线程同时还处理着其余交互逻辑,这就没法保证view更新的速度与帧率了,而SurfaceView能够用独立线程来绘制,所以能够得到更高的帧率。函数
什么是SurfaceHolder性能
API:Abstract interface to someone holding a display surface. Allows you to control the surface size and format, edit the pixels in the surface, and monitor changes to the surface. This interface is typically available through the SurfaceView
class.动画
这是一个接口要经过SurfaceView来实现对Surface的控制,改变尺寸,格式等等。spa
拾人牙慧
一、定义
能够直接从内存或者DMA等硬件接口取得图像数据,是个很是重要的绘图容器,这里与api23之后出现的TextureView不一样。
它的特性是:能够在主线程以外的线程中向屏幕绘图上。这样能够避免画图任务繁重的时候形成主线程阻塞,从而提升了程序的反应速度。在游戏开发中多用到SurfaceView,游戏中的背景、人物、动画等等尽可能在画布canvas中画出。
二、实现
首先继承SurfaceView并实现SurfaceHolder.Callback接口
使用接口的缘由:由于使用SurfaceView 有一个原则,全部的绘图工做必须得在Surface 被建立以后才能开始(Surface—表面,这个概念在 图形编程中经常被提到。基本上咱们能够把它看成显存的一个映射,写入到Surface 的内容
能够被直接复制到显存从而显示出来,这使得显示速度会很是快),而在Surface 被销毁以前必须结束。因此Callback 中的surfaceCreated 和surfaceDestroyed 就成了绘图处理代码的边界。
须要重写的方法
(1)public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){}
//在surface的大小发生改变时激发
(2)public void surfaceCreated(SurfaceHolder holder){}
//在建立时激发,通常在这里调用画图的线程。
(3)public void surfaceDestroyed(SurfaceHolder holder) {}
//销毁时激发,通常在这里将画图的线程中止、释放。
整个过程:继承SurfaceView并实现SurfaceHolder.Callback接口 ----> SurfaceView.getHolder()得到SurfaceHolder对象 ---->SurfaceHolder.addCallback(callback
)添加回调函数---->SurfaceHolder.lockCanvas()得到Canvas对象并锁定画布----> Canvas绘画 ---->SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束锁定画图,并提交改变,将图形显示。
这里lockCanvas-->unclockCanvasAndPost过程要在一个单独的线程里绘画。
在SurfaceHolder源码里面有有一个函数getSurface(),有这么一段解释:
* Direct access to the surface object. The Surface may not always be
* available -- for example when using a {@link SurfaceView} the holder's
* Surface is not created until the view has been attached to the window
* manager and performed a layout in order to determine the dimensions
* and screen position of the Surface. You will thus usually need
* to implement {@link Callback#surfaceCreated Callback.surfaceCreated}
* to find out when the Surface is available for use.
综上所述我的的的理解,一个window都有一个Surface缓冲区,将要显示的数据直接丢进去就能够显示,而SurfaceView是为了得到更高的频率与帧率而不与UI线程性能冲突,因此单独有一个线程来处理绘图,所以它也有一块独立的Surface区,而SurfaceHolder看名字就知道,是能够对Surface进行各类操做的,具体底层怎么实现是api的工做,咱们只要知道它是的功能,而SurfaceHolder与Surface怎么关联的呢,这里的英文解释的很好。这个函数就是得到Surface的直接接口,可是Surface不是一直均可用,当使用SurfaceView的时候一直到surfaceCreated(..)函数调用以前都是不可用的,所以我在现实图像的时候要在surfaceCreated(..)函数调用之后启动画图线程,或者在在调用Camera的时候要在这个函数里传入Holder给Camera才能正确的将图像数据传入到Surface,固然若是推出程序,SurfaceDestroy(..)中释放资源。