1、什么是Surfacejava
简单的说Surface对应了一块屏幕缓冲区,每一个window对应一个Surface,任何View都要画在Surface的Canvas上(后面有缘由解释)。传统的view共享一块屏幕缓冲区,全部的绘制必须在UI线程中进行。android
在SDK的文档中,对Surface的描述是这样的:“Handle onto a raw buffer that is being managed by the screen compositor”,翻译成中文就是“由屏幕显示内容合成器(screen compositor)所管理的原始缓冲区的句柄”,这句话包括下面两个意思:程序员
一、经过Surface(由于Surface是句柄)就能够得到原生缓冲器以及其中的内容。就像在C++语言中,能够经过一个文件的句柄,就能够得到文件的内容同样。canvas
二、 原始缓冲区(a raw buffer)是用于保存当前窗口的像素数据的。设计模式
引申地,能够认为Android中的Surface就是一个用来画图形(graphics)或图像(image)的地方。app
根据Java方面的常规知识,咱们知道一般画图是在一个Canvas对象上面进行的,由此,能够推知一个Surface对象中应该包含有一个Canvas(画布)对象。所以,在前面说起的两个意思的基础上,能够再加上一条:ide
三、Surface中有一个Canvas成员,专门用于画图的。this
由以上的归纳,咱们总结以下:Surface中的Canvas成员,是专门用于供程序员画图的场所,就像黑板同样;其中的原始缓冲区是用来保存数据的地方;Surface自己的做用相似一个句柄,获得了这个句柄就能够获得其中的Canvas、原始缓冲区以及其它方面的内容。spa
Surface是用来管理数据的。(句柄).net
2、什么是SurfaceView
说SurfaceView是一个View也许不够严谨,然而从定义中pubilc classSurfaceView extends View{.....}显示SurfaceView确实是派生自View,可是SurfaceView却有本身的Surface,请看SurfaceView的源码:
[java] view plain copy
<span style="font-size:14px;color:#333333;"> if (mWindow == null) {
mWindow = new MyWindow(this);
mLayout.type = mWindowType;
mLayout.gravity = Gravity.LEFT|Gravity.TOP;
mSession.addWithoutInputChannel(mWindow, mWindow.mSeq, mLayout,
mVisible ? VISIBLE : GONE, mContentInsets);
} </span>
很明显,每一个SurfaceView建立的时候都会建立一个MyWindow,new MyWindow(this)中的this正是SurfaceView自身,所以将SurfaceView和window绑定在一块儿,由第一部分咱们知道,一个window对应一个Surface,所以SurfaceView也就内嵌了一个本身的Surface,能够认为SurfaceView是用来控制Surface中View的位置和尺寸的。
SurfaceView就是展现Surface中数据的地方,同时能够认为SurfaceView是用来控制Surface中View的位置和尺寸的。
你们都知道,传统View及其派生类的更新只能在UI线程,然而UI线程还同时处理其余交互逻辑,这就没法保证View更新的速度和帧率了,而SurfaceView能够用独立的线程进行绘制,所以能够提供更高的帧率,例如游戏,摄像头取景等场景就比较适合SurfaceView来实现。
3、什么是SurfaceHolder
SurfaceHolder是一个接口,其做用就像一个关于Surface的监听器,提供访问和控制SurfaceView内嵌的Surface 相关的方法。它经过三个回调方法,让咱们能够感知到Surface的建立、销毁或者改变。
在SurfaceView中有一个方法getHolder,能够很方便地得到SurfaceView内嵌的Surface所对应的监听器接口SurfaceHolder(有点拗口吧)。
除下面将要提到的SurfaceHolder.Callback外,SurfaceHolder还提供了不少重要的方法,其中最重要的就是:
一、abstract void addCallback(SurfaceHolder.Callbackcallback):为SurfaceHolder添加一个SurfaceHolder.Callback回调接口。
二、abstract Canvas lockCanvas():获取一个Canvas对象,并锁定之。所获得的Canvas对象,其实就是Surface中一个成员。
三、abstract Canvas lockCanvas(Rect dirty):同上。但只锁定dirty所指定的矩形区域,所以效率更高。
四、abstract void unlockCanvasAndPost(Canvas canvas):当修改Surface中的数据完成后,释放同步锁,并提交改变,而后将新的数据进行展现,同时Surface中相关数据会被丢失。
二、三、4中的同步锁机制的目的,就是为了在绘制的过程当中,Surface中的数据不会被改变。lockCanvas是为了防止同一时刻多个线程对同一canvas写入。
总结:从设计模式的高度来看,Surface、SurfaceView和SurfaceHolder实质上就是广为人知的MVC,即Model-View-Controller。Model就是模型的意思,或者说是数据模型,或者更简单地说就是数据,也就是这里的Surface;View即视图,表明用户交互界面,也就是这里的SurfaceView;SurfaceHolder很明显能够理解为MVC中的Controller(控制器)。
4、什么是SurfaceHolder.Callback
SurfaceHolder.Callback主要是当底层的Surface被建立、销毁或者改变时提供回调通知,因为绘制必须在Surface被建立后才能进行,所以SurfaceHolder.Callback中的surfaceCreated 和surfaceDestroyed 就成了绘图处理代码的边界。
SurfaceHolder.Callback中定义了三个接口方法:
一、abstract void surfaceChanged(SurfaceHolder holder, int format, int width, int height):当surface发生任何结构性的变化时(格式或者大小),该方法就会被当即调用。
二、abstract void surfaceCreated(SurfaceHolder holder):当surface对象建立后,该方法就会被当即调用。
三、abstract void surfaceDestroyed(SurfaceHolder holder):当surface对象在将要销毁前,该方法会被当即调用。
5、实例演示
下面,咱们经过一个很是简单例子来实际感觉一下,请留意代码中的注释:
一、在Eclipse中建立一个android Project项目TestSurfaceView,并选择生成缺省的Activity TestSurfaceViewActivity
二、建立一个绘制线程以下:
[java] view plain copy
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
importandroid.view.SurfaceHolder;
// 绘制线程
public class MyThread extends Thread
{
private SurfaceHolder holder;
private boolean run;
public MyThread(SurfaceHolder holder)
{
this.holder = holder;
run = true;
}
@Override
public void run()
{
int counter = 0;
Canvas canvas = null;
while(run)
{
// 具体绘制工做
try
{
// 获取Canvas对象,并锁定之
canvas= holder.lockCanvas();
// 设定Canvas对象的背景颜色
canvas.drawColor(Color.WHITE);
// 建立画笔
Paint p = new Paint();
// 设置画笔颜色
p.setColor(Color.BLACK);
// 设置文字大小
p.setTextSize(30);
// 建立一个Rect对象rect
Rect rect = new Rect(100, 50, 380, 330);
// 在canvas上绘制rect
canvas.drawRect(rect,p);
// 在canvas上显示时间
canvas.drawText("Interval = " + (counter++) + " seconds.", 100, 410, p);
Thread.sleep(1000);
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
if(canvas != null)
{
// 解除锁定,并提交修改内容
holder.unlockCanvasAndPost(canvas);
}
}
}
}
public boolean isRun()
{
return run;
}
public void setRun(boolean run)
{
this.run = run;
}
}
三、自定义一个SurfaceView类以下:
[java] view plain copy
import android.content.Context;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MySurfaceView extends SurfaceView<span style="font-family:Arial;"> </span>implements<span style="font-family:Arial;"> </span>SurfaceHolder.Callback
{
private SurfaceHolder holder;
private MyThread myThread;
public MySurfaceView(Context context)
{
super(context);
// 经过SurfaceView得到SurfaceHolder对象
holder = getHolder();
// 为holder添加回调结构SurfaceHolder.Callback
holder.addCallback(this);
// 建立一个绘制线程,将holder对象做为参数传入,这样在绘制线程中就能够得到holder
// 对象,进而在绘制线程中能够经过holder对象得到Canvas对象,并在Canvas上进行绘制
myThread = new MyThread(holder);
}
// 实现SurfaceHolder.Callback接口中的三个方法,都是在主线程中调用,而不是在绘制线程中调用的
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
// 启动线程。当这个方法调用时,说明Surface已经有效了
myThread.setRun(true);
myThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
// 结束线程。当这个方法调用时,说明Surface即将要被销毁了
myThread.setRun(false);
}
}
四、修改TestSurfaceViewActivity.java代码,使之以下:
[java] view plain copy
import android.app.Activity;
import android.os.Bundle;
public class TestSurfaceViewActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
setContentView(new MySurfaceView(this));
}
}
总结:从设计模式的高度来看,Surface、SurfaceView和SurfaceHolder实质上就是广为人知的MVC,即Model-View-Controller。Model就是模型的意思,或者说是数据模型,或者更简单地说就是数据,也就是这里的Surface;View即视图,表明用户交互界面,也就是这里的SurfaceView;SurfaceHolder很明显能够理解为MVC中的Controller(控制器)。