可以认为Android中的Surface就是一个用来画图形(graphics)或图像(image)的地方。根据Java方面的常规知识,我们知道通常画图是在一个Canvas对象上面进行的,由此,可以推知一个Surface对象中应该包含有一个Canvas对象,事实上的确如此
SurfaceView,顾名思义就是Surface的View,通过SurfaceView就可以看到Surface的部分或者全部的内容,下面用一个图来形象地描述一下Surface和SurfaceView的关系:
SurfaceHolder是一个接口,其作用就像一个关于Surface的监听器。提供访问和控制SurfaceView背后的Surface 相关的方法 (providingaccess and control over this SurfaceView's underlying surface),它通过三个回调方法,让我们可以感知到Surface的创建、销毁或者改变。在SurfaceView中有一个方法getHolder,可以很方便地获得SurfaceView所对应的Surface所对应的SurfaceHolder。
s
urfaceHolder通过回到方法的方式,让我们可以感知到Surface的创建、销毁或者改变。其实这一点是通过其内部的静态子接口SurfaceHolder.Callback来实现的。SurfaceHolder.Callback中定义了三个接口方法:
implements SurfaceHolder.Callback 需要实现的接口有如是3个方法
-
//当surface发生任何结构性的变化时(格式或者大小),该方法就会被立即调用。
-
@Override
-
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
-
// TODO Auto-generated method stub
-
}
-
-
//当surface对象创建后,该方法就会被立即调用。
-
@Override
-
public void surfaceCreated(SurfaceHolder arg0) {
-
// TODO Auto-generated method stub
-
}
-
-
//当surface对象在将要销毁前,该方法会被立即调用。
-
@Override
-
public void surfaceDestroyed(SurfaceHolder arg0) {
-
// TODO Auto-generated method stub
-
}
除SurfaceHolder.Callback外,SurfaceHolder还提供了很多重要的方法,其中最重要的就是:
1. abstract void (callback)
为SurfaceHolder添加一个SurfaceHolder.Callback回调接口。
2. abstract ()
获取一个Canvas对象,并锁定之。所得到的Canvas对象,其实就是Surface中一个成员。
3. abstract (dirty)
同上。但只锁定dirty所指定的矩形区域,因此效率更高。
4. abstract void (canvas)
当修改Surface中的数据完成后,释放同步锁,并提交改变,然后将新的数据进行展示,同时Surface中相关数据会被丢失。
5. public abstract void setType (int type)
设置Surface的类型,接收如下的参数:
SURFACE_TYPE_NORMAL:用RAM缓存原生数据的普通Surface
SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access )引擎和硬件加速的Surface
SURFACE_TYPE_GPU:适用于GPU加速的Surface
SURFACE_TYPE_PUSH_BUFFERS:表明该Surface不包含原生数据,Surface用到的数据由其他对象提供,在Camera图像览中就使用该类型的Surface,有Camera负责提供给预览Surface数据,这样图像预览会比较流畅。如果设置这种类型则就不能调用lockCanvas来获取Canvas对象了。需要注意的是,在高版本的Android SDK中,setType这个方法已经被depreciated了。
2、3、4中的同步锁机制的目的,就是为了在绘制的过程中,Surface中的数据不会被改变。
从设计模式的高度来看,Surface、SurfaceView和SurfaceHolder实质上就是广为人知的MVC。Mode就是这里的Surface;View即是这里的SurfaceView;SurfaceHolder可以理解为MVC中的Controller。这样看起来三者之间的关系就清楚了很多。
SurfaceView目的之一,就是提供一个可以用另外一个线程(第二个线程)进行屏幕渲染的surface(译注:即UI线程和绘制线程可以分离)。如果你打算这样使用,那么应当注意一些线程方面的语义,所有SurfaceView和SurfaceHolder.Callback中声明的方法,必须在运行SurfaceView窗口中的线程中调用(典型地,就是应用的主线程。译注:即UI线程),因为它们需要正确地将同时被绘制线程访问的各种状态进行同步。必须保证,只有在背后的Surface有效的时候 – 在SurfaceHolder.Callback.surfaceCreated()和 SurfaceHolder.Callback.surfaceDestroyed()这两个方法调用之间,访问它。
下面是一个测试例子
代码来自http://www.cnblogs.com/xuling/archive/2011/06/06/android.html
-
package xl.test;
-
-
import android.app.Activity;
-
import android.content.Context;
-
import android.graphics.Canvas;
-
import android.graphics.Color;
-
import android.graphics.Paint;
-
import android.graphics.Rect;
-
import android.os.Bundle;
-
import android.view.SurfaceHolder;
-
import android.view.SurfaceView;
-
-
public class ViewTest extends Activity {
-
/** Called when the activity is first created. */
-
@Override
-
public void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(new MyView(this));
-
}
-
//视图内部类
-
class MyView extends SurfaceView implements SurfaceHolder.Callback
-
{
-
private SurfaceHolder holder;
-
private MyThread myThread;
-
public MyView(Context context) {
-
super(context);
-
// TODO Auto-generated constructor stub
-
holder = this.getHolder();
-
holder.addCallback(this);
-
myThread = new MyThread(holder);//创建一个绘图线程
-
}
-
-
@Override
-
public void surfaceChanged(SurfaceHolder holder, int format, int width,
-
int height) {
-
// TODO Auto-generated method stub
-
-
}
-
-
@Override
-
public void surfaceCreated(SurfaceHolder holder) {
-
// TODO Auto-generated method stub
-
myThread.isRun = true;
-
myThread.start();
-
}
-
-
@Override
-
public void surfaceDestroyed(SurfaceHolder holder) {
-
// TODO Auto-generated method stub
-
myThread.isRun = false;
-
}
-
-
}
-
//线程内部类
-
class MyThread extends Thread
-
{
-
private SurfaceHolder holder;
-
public boolean isRun ;
-
public MyThread(SurfaceHolder holder)
-
{
-
this.holder =holder;
-
isRun = true;
-
}
-
@Override
-
public void run()
-
{
-
int count = 0;
-
while(isRun)
-
{
-
Canvas c = null;
-
try
-
{
-
synchronized (holder)
-
{
-
c = holder.lockCanvas();//锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。
-
c.drawColor(Color.BLACK);//设置画布背景颜色
-
Paint p = new Paint(); //创建画笔
-
p.setColor(Color.WHITE);
-
Rect r = new Rect(100, 50, 300, 250);
-
c.drawRect(r, p);
-
c.drawText("这是第"+(count++)+"秒", 100, 310, p);
-
Thread.sleep(1000);//睡眠时间为1秒
-
}
-
}
-
catch (Exception e) {
-
// TODO: handle exception
-
e.printStackTrace();
-
}
-
finally
-
{
-
if( null)
-
{
-
holder.unlockCanvasAndPost(c);//结束锁定画图,并提交改变。
-
-
}
-
}
-
}
-
}
-
}
-
}
阅读(1517) | 评论(0) | 转发(0) |