一、SurfaceView 与 View 的区别
surfaceView是在一个新起的单独线程中可以重新绘制画面,而View必须在UI的主线程中更新画面。那么在UI的主线程中更新画面 可能会引发问题,比如你更新画面的时间过长,那么你的主UI线程会被你正在画的函数阻塞。那么将无法响应按键,触屏等消息。当使用surfaceView 由于是在新的线程中更新画面所以不会阻塞你的UI主线程。但这也带来了另外一个问题,就是事件同步。比如你触屏了一下,你需要surfaceView中 thread处理,一般就需要有一个event queue的设计来保存touch event,这会稍稍复杂一点,因为涉及到线程同步。
二、SurfaceView 使用步骤
1.获取到 SurfaceView 对应的 SurfaceHolder,给 SurfaceHolder 添加一个 SurfaceHolder.callback 对象。
2.创建渲染线程对象
3.在子线程中开始在 Surface 上面绘制图形,因为SurfaceView没有对我们暴露 Surface,而只是暴露了 Surface 的包装器 SurfaceHolder,所以使用 SurfaceHolder 的 lockCanvas()获取 Surface 上面指定区域的 Canvas,在该 Canvas 上绘制图形,绘制结束后,使用 SurfaceHolder 的 unlockCanvasAndPost()方法解锁 Canvas,并且让 UI 线程把 Surface 上面的东西绘制到 View 的 Canvas 上面
三、Demo
public class GameUI extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder holder;
private RenderThread renderThread;
private boolean isDraw = false;// 控制绘制的开关
public GameUI(Context context) {
super(context);
holder = this.getHolder();
holder.addCallback(this);
renderThread = new RenderThread();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
isDraw = true;
renderThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
isDraw = false;
}
/**
* 绘制界面的线程
* @author Administrator
*
*/
private class RenderThread extends Thread {
@Override
public void run() {
// 不停绘制界面
while (isDraw) {
drawUI();
}
super.run();
}
}
/**
* 界面绘制
*/
public void drawUI() {
Canvas canvas = holder.lockCanvas();
try {
drawCanvas(canvas);
} catch (Exception e) {
e.printStackTrace();
} finally {
holder.unlockCanvasAndPost(canvas);
}
}
private void drawCanvas(Canvas canvas) {
// 在 canvas 上绘制需要的图形
}
}