SurfaceView的介绍:
我们可以自定义View,重写onDraw利用canvas进行绘图。但是,onDraw不能执行太耗时的操作,View是通过刷新来重绘视图的,刷新的间隔是16ms,所以在16ms要执行完绘图操作,不然就会出现卡顿。为了解决这一问题,Android提供了SurfaceView来解决这个问题。它与View的区别主要有以下几点:
- View是在主线程中对画面进行刷新,而Surface通常会通过一个子线程来进行页面的刷新。
- View在绘图时没有使用双缓冲机制,而SurfaceView在低层实现机制中就已经实现了双缓冲机制。
- View主要适用于主动更新的情况下,而SurfaceView主要适用于被动更新。
所以呢,如果你的View需要频繁刷新的话,或者刷新时数据处理量比较大,就可以考虑选用SurfaceView来处理。
SurfaceView的一般使用方法:
1、自定义一个子类继承Surface,并实现两个接口,即SurfaceView.Callback和Runnable,并且实现这两个接口的方法。代:码如下
public class MyView extends SurfaceView implemnts SurfaceHolder,Runnable
{
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void surfaceCreated(SurfaceHolder holder)
<span style="white-space:pre"> </span>{}
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void surfaceChanged(SurfaceHolder holder,int format,int width,int height)
<span style="white-space:pre"> </span>{}
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void surfaceDestroyed(SurfaceHolder holder)
<span style="white-space:pre"> </span>{}
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void run()
<span style="white-space:pre"> </span>{}
}
前三个方法分别是于Surface的创建、创建和销毁的回调方法,最后一个run方法是实现Runnable接口的。
2、初始化SurfaceView
通常要设置这样三个成员变量,代码如下:
//SurfaceHolder,主线程的Holder,用来实现回调
private SurfaceHolder mHolder;
//用来绘图的Canvas
private Canvas mCanvas;
//子线程的标志位
private boolean mIsDrawing;
mHolder是获取主线程的Holder,用来实现SurfaceHolder.Callback的回调。mCanvas就是像View一样,用来绘图的。最后mIsDrawing来标志子线程何时结束绘图。
3、使用SurfaceView。
可以通过SurfaceView的lockCanvas方法,可以获取得到当前Canvas的绘图对象。注意,获取的Canvas对象还是以前的Canvas对象,不是新的一个对象,还是会保存着之前的绘图操作,如果需要去除之前的绘图操作,通过drawColor()方法来进行清屏操作。
下面就是SurfaceView的使用例子代码:
public class MyView extends SurfaceView implemnts SurfaceHolder,Runnable
{
//SurfaceHolder
private SurfaceHolder mHolder;
//用来绘图的Canvas
private Canvas mCanvas;
//子线程的标志位
private boolean mIsDrawing
public MyView(Context context)
{
super(context);
initView();
}
public MyView(Context context,AttributeSet attrs)
{
super(context,attrs);
initView();
}
public SurfaceView(Context context,AttributeSet attrs,int defStyle)
{
super(context,attrs,defStyle);
initView();
}
private void initView()
{
mHolder = getHolder();
mHolder.addCallback(this);
this.setKeepScreenOn(true);
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
mIsDrawing = true;
new Thread(this).start();
}
@Override
public void surfaceChanged(SurfaceHolder holder,int format,int width,int height)
{}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
mIsDrawing = false;
}
@Override
public void run()
{
while(mIsDrawing)
{
try{
mCanvas = mHolder.lockCanvas();
draw(mCanvas);
}
catch(Exception e){
}
finally{
if(mCanvas != null)
{
mHolder.unlockCanvasAndPost(mCanvas);
}
}
}
}
private void draw(Canvas canvas)
{
//执行自己的绘图操作。
}
}