android进阶-surfaceView的分析和使用

来源:互联网 发布:淘宝店铺改名字 编辑:程序博客网 时间:2024/06/07 15:55

**

1.surfaceView与View的区别

**
View通过刷新来重绘视图,Android系统通过发出VSYNC信号来进行屏幕的重绘,刷新时间间隔为16ms。如果16ms内View完成了需要执行的所有操作,不会在视觉上出现卡顿的感觉,反之,则会出现。
surfaceView的出现就是解决这个问题。
surefaceView和Viewde 区别:
(1)View主要适用于主动更新的情况下,而SurfaceView主要适用于被动更新,例如频繁的刷新。
(2)View在主线程中对画面进行刷新,而surface通过一个子线程来进行页面的刷新。
(3)View在绘图时没有使用双缓冲机制,而SurfaceView在底层实现机制中就已经实现双缓冲机制
双缓冲机制:
参见:http://www.yafeilinux.com/?p=73

不用画布,直接在窗口上进行绘图叫做无缓冲绘图。用了一个画布,将所有内容都先画到画布上,在整体绘制到窗口上,就该叫做单缓冲绘图,那个画布就是一个缓冲区。用了两个画布,一个进行临时的绘图,一个进行最终的绘图,这样就叫做双缓冲绘图。

surfaceView自身实现了双缓冲,而View没有。其实view你也可以自己实现,但是实现的结构不如surfaceView好。

surfaceView通过 surfaceHolder.lockCanvas 锁定画布,实现下一张图片的绘制,再通过另外的线程刷新界面,绘制图片。view则是直接在ondraw里绘制图片,刷新界面。其实view也可以实现双缓冲机制,你可以在另个出ondraw的方法中绘制下一张bitmap(参见:

http://blog.csdn.net/liubingzhao/article/details/5563113

),也可以另开一个线程,处理除了绘制图片以外的操作(参见:

http://topic.csdn.net/u/20110901/23/e283f805-20dc-40c3-8381-403dd1ca69b0.html

),就实现了view的双缓冲。
为什么动态绘图surfaceView要比View好?

因为View是在UI主线程中进行绘制的,绘制时会阻塞主线程,如果ontouch事件又处理的比较多的话会导致界面卡。而surfaceView是另开了一个线程绘制的,再加上双缓冲机制,所以要高效。不会卡。其实现在一般实现view的时候一般都会在其他出先生成bitmap在给ondraw去画,所以双缓冲的作用不是那么明显了(个人认为)。

**

2.SurfaceView的使用

**
(1)创建SurfaceView
创建自定义的SurfaceView继承自SurfaceView,并实现两个接口-SurfaceHolder.CallBack和Runable

public class SimpleDraw extends SurfaceView        implements SurfaceHolder.Callback, Runnable {

实现接口的方法:
分别对应SurfaceView的创建、改变和销毁过程。

 @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;    }

(2)初始化SurfaceView
在自定义SurfaceView的构造方法中,需要对SurfaceView进行初始化。
定义以下三个成员变量

private SurfaceHolder mHolder;//用于绘图的Canvas    private Canvas mCanvas;//子线程标志位    private boolean mIsDrawing;

初始化SurfaceView

  mHolder = getHolder();   mHolder.addCallback(this);

(3)使用SurfaceView
通过SurfaceHolder对象的lockCanvas()方法,就可以获取当前的Canvas绘图对象。这里获取的Canvas对象还是继续上次的Canvas对象,而不是一个新的对象。需要擦出,则可以在绘制前调用drawColor()方法来进行清屏操作。
整个SurfaceView的模版代码如下

package com.imooc.surfaceviewtest;import android.content.Context;import android.graphics.Canvas;import android.util.AttributeSet;import android.view.SurfaceHolder;import android.view.SurfaceView;public class SurfaceViewTemplate extends SurfaceView        implements SurfaceHolder.Callback, Runnable {    // SurfaceHolder    private SurfaceHolder mHolder;    // 用于绘图的Canvas    private Canvas mCanvas;    // 子线程标志位    private boolean mIsDrawing;    public SurfaceViewTemplate(Context context) {        super(context);        initView();    }    public SurfaceViewTemplate(Context context, AttributeSet attrs) {        super(context, attrs);        initView();    }    public SurfaceViewTemplate(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        initView();    }    private void initView() {        mHolder = getHolder();        mHolder.addCallback(this);        setFocusable(true);        setFocusableInTouchMode(true);        this.setKeepScreenOn(true);        //mHolder.setFormat(PixelFormat.OPAQUE);    }    @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) {            draw();        }    }    private void draw() {        try {            mCanvas = mHolder.lockCanvas();            // draw sth        } catch (Exception e) {        } finally {            if (mCanvas != null)                mHolder.unlockCanvasAndPost(mCanvas);        }    }}

注意将mHolder.unlockCanvasAndPost(mCanvas)方法放在finally代码块中,保证每次内容提交。、

SurfaceView实例
这里写图片描述

实例地址:
下载地址

原创粉丝点击