介绍Surface View
正常的情况,所有APP的View都在UI线程中画的。同时,主线程也是用来用户交互的。
我们都知道不能堵塞线程,View的onDraw方法是在主线程中运行的。 同样的,直接在后台线程中修改UI元素是不被允许的。
当你想去快速地更新UI,不想你的渲染代码堵塞主线程(UI线程),SurfaceView就是答案。
SurfaceView封装着一个Surface对象而不是Canvas对象。 这点很重要,Surface是可以在后台线程画的。这可以应用在:3D图像,游戏,Camera的实时预览。
尽管看起来有点很多,但是也是有代价的,内存消耗同比增加,所以你确定要用再去使用。
使用SurfaceView有些地方跟View这些用起来一样,你也仍然可以应用动画在上面,布局啊 等等。
Surface支持画(以前Canvas用的手段),还支持OPENGL ES库。
创建Surface View
首先你需要继承SurfaceView,然后你需要实现SurfaceHolder.Callback。
SurfaceHolder的callback提醒着SurfaceView,当它被创建,销毁和修改。 SurfaceView保持着对SurfaceHolder的引用,SurfaceHolder包含着一个可用的Surface对象。
下面这个例子,一个SurfaceView 框架代码:
import android.content.Context;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MySurfaceView extends SurfaceView implements
SurfaceHolder.Callback {
private SurfaceHolder holder;
private MySurfaceViewThread mySurfaceViewThread;
private boolean hasSurface;
MySurfaceView(Context context) {
super(context);
init();
}
private void init() {
// Create a new SurfaceHolder and assign this
// class as its callback.
holder = getHolder();
holder.addCallback(this);
hasSurface = false;
}
public void resume() {
// Create and start the graphics update thread.
if (mySurfaceViewThread == null) {
mySurfaceViewThread = new MySurfaceViewThread();
if (hasSurface == true)
mySurfaceViewThread.start();
}
}
public void pause() {
// Kill the graphics update thread
if (mySurfaceViewThread != null) {
mySurfaceViewThread.requestExitAndWait();
mySurfaceViewThread = null;
}
}
public void surfaceCreated(SurfaceHolder holder) {
hasSurface = true;
if (mySurfaceViewThread != null)
mySurfaceViewThread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false;
pause();
}
public void surfaceChanged(SurfaceHolder holder, int format,
int w, int h) {
if (mySurfaceViewThread != null)
mySurfaceViewThread.onWindowResize(w, h);
}
class MySurfaceViewThread extends Thread {
private boolean done;
MySurfaceViewThread() {
super();
done = false;
}
@Override
public void run() {
SurfaceHolder surfaceHolder = holder;
// Repeat the drawing loop until the thread is stopped.
while (!done) {
// Lock the surface and return the canvas to draw onto.
Canvas canvas = surfaceHolder.lockCanvas();
// TODO: Draw on the canvas!
// Unlock the canvas and render the current image.
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
public void requestExitAndWait() {
// Mark this thread as complete and combine into
// the main application thread.
done = true;
try {
join();
} catch (InterruptedException ex) { }
}
public void onWindowResize(int w, int h) {
// Deal with a change in the available surface size.
}
}
}
3D视图与SurfaceView与OPEGL相关,这里先不讨论了。