04 SurfaceView-使用

作者: 凤邪摩羯 | 来源:发表于2021-07-15 09:19 被阅读0次

    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

    相关文章

      网友评论

        本文标题:04 SurfaceView-使用

        本文链接:https://www.haomeiwen.com/subject/dtgmaktx.html