安卓 SurfaceView 和 View 的区别和使用方法

Android 系统提供了 View 进行绘图处理,View 可以满足大部分的绘图需求,但在某些时候,View 通过刷新来重绘视图,Android 系统通过发出 vsync 信号来进行屏幕重绘,刷新的间隔时间为 16ms,如果在这个时间间隔内完成了你所需要执行的所有操作,那么在视觉上,就不会产生卡顿的感觉,而如果执行的操作逻辑太多,特别再需要频繁刷新的界面上,例如游戏界面,那么就会不断阻塞主线程,从而导致界面卡顿,为了避免这个问题,Android 系统提供了 surfaceView 组件来解决这个问题。surfaceView 和 View 的区别主要有下面几点:

  • View 主要适用于主动更新的情况,而 surfaceView 主要适用于被动更新,例如频繁的刷新。
  • View 在主线程中对画面进行刷新,而 surfaceView 通常会通过一个子线程来进行页面的刷新
  • View 在绘图时没有使用双缓冲机制,而 surfaceView 在底层实现机制上就已经实现了双缓冲机制。
    总结就是,如果你的自定义 View 需要频繁刷新,或者刷新时数据处理量很大,考虑用 SurfaceView 来替代 View。

surfaceView 的使用

  • 创建 SurfaceView,一般我们实现 SurfaceHolder.Callback, Runnable接口
    //surfaceView 的创建
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mIsDraw = true;
    }
    //surfaceView 的改变
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }
    //surfaceView 的销毁
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mIsDraw = false;
    }
 //runnable 的run 方法中,我们可以执行绘制的操作
    @Override
    public void run() {
        while (mIsDraw) {
            draw();
        }
    }
  • 初始化 surfaceView
mHolder = getHolder();
mHolder.addCallback(this);
//通过 lockCanvas 方法可以获得当前的 canvas 绘图对象,接下来,就可以与在 View 中进行的绘制操作一样了
mCanvas = mHolder.lockCanvas();
//通过 unlockCanvasAndPost 方法可以对当前画布内容进行提交。
mHolder.unlockCanvasAndPost(mCanvas);

下面是一个 surfaceView 使用的模板,基本上可以在这个基础上来修改满足大部分的绘图需求。

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

    private SurfaceHolder mHolder;
    private boolean mIsDraw;
    private Canvas mCanvas;

    public SurfaceViewDemo(Context context) {
        super(context);
        initView();
    }

    public SurfaceViewDemo(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    public SurfaceViewDemo(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public SurfaceViewDemo(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initView();
    }


    private void initView() {
        mHolder = getHolder();
        mHolder.addCallback(this);
        setFocusable(true);
        setFocusableInTouchMode(true);
        setKeepScreenOn(true);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mIsDraw = true;
        new Thread(this).start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mIsDraw = false;
    }

    //runnable 的run 方法中,我们可以执行绘制的操作
    @Override
    public void run() {
        while (mIsDraw) {
            draw();
        }
    }

    private void draw() {
        mCanvas = mHolder.lockCanvas();
        //draw something
        
        mHolder.unlockCanvasAndPost(mCanvas);
    }
}

下面是一些 surfaceView 的实例源码的地址:https://github.com/MoveToNext/SurfaceViewDemo

你可能感兴趣的:(安卓 SurfaceView 和 View 的区别和使用方法)