开讲前,先从View说起吧。
View类,是Android的一个超类,每个View都有一个用于绘画的画布,这个画布可以进行任意的扩展。当需要绘制复杂的图像或者对线程的执行效率要求比较高的时候,View就不能满足全部的要求了。View是Widget框架下的一个直接拖拉的控件产物。例如:当需要双缓冲来显示,直接访问画布Canvas,这写就导致了当前View无法满足我们的要求了。因此,功能更加强大效率更高的SurfaceView就诞生了。
以下几条说明基本均翻译自google提供的Android API:
1、SurfaceView是View的继承类,这个视图里内嵌了一个专门用来绘制的Surface。我们可以控制这个Surface的格式和尺寸。SurfaceView控制这个Surface的绘制位置。具体专业来讲:SurfaceView基于是基于View视图进行拓展的视图类,更适合2D游戏的开发,是View的子类,使用了双缓冲机制,在新的线程中更新画面,所以新界面速度比View要快。
2、SurfaceView是纵深排序的,这说明它总是在自己所在窗口的后面。SurfaceView提供了一个可见区域,只有在这个可见区域内的surface部分内容才可见,可见区域外部部分不可见。
3、SurfaceView变得可见时,surface被创建,surfaceView隐藏前,surface被毁灭。这样可以节省资源
4、SurfaceView核心提供了两个线程,UI线程和渲染线程。应当注意的是:
a:所有的SurfaceView和SurfaceHolder.CallBack的方法都应该在UI线程里调用,一般来说就是应用程序的主线程。渲染线程所要访问的各种变量应该做同步处理。
b:由于suface可能被销毁,它只在SurfaceHolder.CallBack.surfaceCreated()和SurfaceHolder.Callback.surfaceDestroyed()之间有效,所以要确保渲染线程访问的是合法有效的surface
一、SurfaceView和View的区别:
SurfaceView可以直接从内存或者DMA等硬件接口取得图像数据,是个非常重要的绘图容器。其特性是:可以在主线程之外的线程中向屏幕上绘图。这样可以避免画图任务繁重时造成主线程阻塞,从而提高程序的反应速度。
SurfaceView和View最本质的区别在于,surfaceView是在一个新启动的单独线程中可以进行重新绘制画面,而View必须在UI的主线程中更新画面。那么在UI的主线程中更新画面,可能会引发问题,比如:更新画面的时间过长,那么主线程会被正在绘画的函数锁阻塞,有可能导致程序假死。当使用surfaceView时,由于是在新的线程中更新画面所以不会阻塞UI主线程。
View:必须在UI主线程中更新画面,用于被动更新画面。
SurfaceView:UI主线程和子线程都可以,在一个新启动的线程中会重新绘制画面,主动更新画面。
二、具体实现
1、自定义一个类MySurfaceView继承SurfaceView并实现SurfaceView.Callback接口
使用接口的原因:因为使用SurfaceView有一个原则,所有的绘图工作必须得在SurfaceView被创建之后才能开始,而在Surface被销毁之前必须结束。所以Callback中的surfaceCreated和surfaceDestroyed就成了绘图代理代码的边界。需要重写的方法:
a:public void surfaceChanged)//surface的大小发生改变时进行调用
b:public void surfaceDestroyed()//销毁时激发,一般在这里将画面的线程停止,释放
c:public void addCallback();//给surfaceView添加一个回调函数
d:public void lockCanvas();//锁定画布,绘图之前必须锁定画布才能得到画布对象
e:public void surfaceCreated();//创建时激发,一般在这里调用画面的线程
f:public void unLockCanvasAndPost();//开始绘制时锁定了画布,绘制完成之后解锁画布
g:public void removeCallback();//从surfaceView中移除回调函数
2、得到SurfaceHolder对象。调用SurfaceView.getHolder()方法获取surfaceHolder对象
3、添加回调函数:SurfaceHolder.addCallback(callBack)添加回调函数
4、获取Canvas对象并锁定画布:SurfaceHolder.lockCanvas()
5、Canvas绘画
6、结束锁定画图,提交改变,将图形显示。SurfaceHolder.unlockCanvasCanvasAndPost(Canvas canvas)
三、关于SurfaceHolder
此处用到的SurfaceHolder,可以理解成Surface的控制器,用来操作surface。处理它的Canvas上画的效果和动画,控制表面、大小、像素等等。
几个常用的方法:
a:abstract void addCallback();//给SurfaceView当前的持有者一个回调函数
b:abstract Canvas lockCanvas();//锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面等操作了。
c:abstract Canvas lockCanvas(Rect dirty);//锁定画布的某个区域进行画图等,
d:abstract void unlockCanvasAndPost(Canvas canvas);//结束锁定画图,提交改变。