android进阶-surfaceView的分析和使用

**

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实例
这里写图片描述

实例地址:
下载地址

猜你喜欢

转载自blog.csdn.net/qq_20967339/article/details/78638465