1. SurfaceView有什么作用?
众所周知,View组件只有在UI(主)线程中绘图,而且必须快速,即不能阻塞主线程。这样的要求对于刷新频率高、绘图工作量大的游戏来说,是致命的缺陷,所以SurfaceView为此而生。
• SurfaceView关键特性:
SurfaceView 与View相比,其关键特性为:在主线程之外的线程中向屏幕上绘图。这样就可以避免在画图任务繁重的时候造成主线程阻塞,从而提高程序的反应速度。
• SurfaceView功能简介:
SurfaceView提供了一个专用于画图的Surface(做事的家伙),还有一个管家SurfaceHolder,自已做老板接客。
通过SurfaceView的SurfaceHolder可以控制Surface的格式、尺寸;且负责把Surface放于屏幕上正确的问题。
Surface是纵深排序(Z-ordered)的,即它总是在自己所在窗口的后面。SurfaceView在它所在的Window中打一个洞,以允许它的Surface显示出来。View树图负责合成SurfaceView的Surface和其它显示在Surface之上的SurfaceView控件。这意味者 surface的内容会被它的兄弟视图遮挡,这一特性可以用来放置遮盖物(overlays)(例如,文本和按钮等控件)。注意,如果Surface上面有透明控件,那么它的每次变化都会引起框架重新计算它和顶层控件的透明效果,这会影响性能。
使Surface可见的透明区域由View树图中的Layout位置决定的。
2. SurfaceView的家族图谱
3. SurfaceView使用方法
1) 通过SurfaceView.getHolder()获取SurfaceHolder接口
2) SurfaceView中的Surface何时被创建、变化和销毁?
当SurfaceView的Window可见时,应用需要实现SurfaceHolder.Callback的接口来得知Surface被创建、变化和销毁的消息
3) SurfaceView的目的:提供了一个Surface,非UI(主)线程(即Render线程)通过此Surface可以把内容绘制到屏幕上。
4) UI(主)线程与Render线程的分工:
• UI(主)线程:所有SurfaceView和SurfaceHolder.Callback的方法都由UI(主)线程调用
• Render线程:Render线程只有在SurfaceHolder.Callback.surfaceCreated()与
SurfaceHolder.Callback.surfaceDestroyed() 之间
可以通过Surface来画图。
• 由于存在两个线程,对于共享对象,需要进行同步访问。
5) 应用实现过程:
• UI(主线程): 继承SurfaceView并实现SurfaceHolder.Callback接口,必须复写的SurfaceHolder.Callback的3个函数:
//启动【Render线程】开始画图,但只能在一个线程中画
public void surfaceCreated(SurfaceHolder holder);
//Surface结构发生变化,需要重画
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height);
//停止【Render线程】画图,此函数返回时,Surface才真正地被销毁
public void surfaceDestroyed(SurfaceHolder holder);
• UI(主线程): 调用 SurfaceView.getHolder()获得SurfaceHolder对象
• UI(主线程): 调用SurfaceHolder.addCallback(callback)添加回调函数
• Render线程: 调用SurfaceHolder.lockCanvas()获得Canvas对象并锁定画布
• Render线程: 调用Canvas的画图函数画图
• Render线程: 调用SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束锁定画图,并将图形显示