View和SurfaceView的刷新抉择

目录

1.view的刷新

2.View和SurfaceView主要区别

3.SurfaceView使用模板

4.示例-绘制正弦函数

5.根据触屏XY坐标绘制路径


1.view的刷新

在自定义view时候,如果要重绘View,我们会调用invalidate(),如果同时某些子控件的位置等也需要变化,我们还会调用requestLayout()。在通知控件的重绘方式上,可以选择handler或者控件自身自带的post(new Runnable)方法。

局限:系统通过发出VSYNC信号通知屏幕重绘的频率为16ms,如果重绘时候执行逻辑操作太多,就会卡顿,甚至阻断主线程。

其实有时候,可以用surfaceView替代view,去做一些频繁的刷新工作。

2.View和SurfaceView主要区别

1.view主要适用与主动刷新,SurfaceView适用于被动刷新

2.view在主线程对画面进行刷新,SurfaceView会自起子线程对画面刷新

3.view在绘图时没有双缓冲机制,SurfaceView在底层实现机制中实现了双缓冲机制

所有,当我们需要频繁刷新,或者刷新是需要处理大量数据逻辑,便可选择SurfaceView。

3.SurfaceView使用模板

大部分SurfaceView绘图都可使用的模板

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

    private SurfaceHolder surfaceHolder;
    //绘图对象
    private Canvas canvas;
    //控制线程是否去绘制
    private boolean isDrawing;

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

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

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

    public void initView() {
        surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);
        setFocusable(true);
        setFocusableInTouchMode(true);
        this.setKeepScreenOn(true);
        //surfaceHolder.setFormat(PixelFormat.OPAQUE);
    }

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

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

    }

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

    @Override
    public void run() {
        while (isDrawing) {
            draw();
        }
    }

    private void draw() {
        try {
            //拿到绘图对象
            canvas = surfaceHolder.lockCanvas();
            //绘制内容
        } catch (Exception e) {
            Log.e("draw: ", e.toString());
        } finally {
            //将绘图的内容提交
            surfaceHolder.unlockCanvasAndPost(canvas);
        }
    }
}

3和比较重要的地方:

1.通过boolean值标志位,去控制界面是否重绘

2.通过SurfaceHolder拿到绘图对象

3.绘制成功后,提交绘制内容

4.示例-绘制正弦函数

核心思想:通过子线程去计算绘制的正弦函数的路径,在draw方法中用lockCanvas()获取到的绘图对象去绘制路径。

代码:修改模板中的run方法和绘制的内容。

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

    private SurfaceHolder surfaceHolder;
    private Canvas canvas;
    private boolean isDrawing;
    //绘制路径
    private Path mPath;
    //path中每个点的坐标
    private int x,y=0;
    private Paint paint;

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

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

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

    public void initView() {
        surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);
        setFocusable(true);
        setFocusableInTouchMode(true);
        this.setKeepScreenOn(true);
        //surfaceHolder.setFormat(PixelFormat.OPAQUE);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        isDrawing = true;
        mPath = new Path();
        mPath.moveTo(0,200);
        paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(5);
        paint.setColor(Color.GREEN);
        paint.setAntiAlias(true);
        new Thread(this).start();
    }

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

    }

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

    @Override
    public void run() {
        while (isDrawing) {
            draw();
            x += 1;
            y = (int) (200 * Math.sin(x * 2 * Math.PI / 180)+200);
            mPath.lineTo(x,y);
        }
    }

    private void draw() {
        try {
            //拿到绘图对象
            canvas = surfaceHolder.lockCanvas();
            canvas.drawColor(Color.WHITE);
            canvas.drawPath(mPath,paint);
            //绘制内容
        } catch (Exception e) {
            Log.e("draw: ", e.toString());
        } finally {
            //将绘图的内容提交
            surfaceHolder.unlockCanvasAndPost(canvas);
        }
    }
}

效果:

https://img-blog.csdnimg.cn/2019030710234643.png

5.根据触屏XY坐标绘制路径

效果:

https://img-blog.csdnimg.cn/20190307105615474.png

代码:

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

    private SurfaceHolder surfaceHolder;
    private Canvas canvas;
    private boolean isDrawing;
    //绘制路径
    private Path mPath;
    private Paint paint;

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

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

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

    public void initView() {
        surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);
        setFocusable(true);
        setFocusableInTouchMode(true);
        this.setKeepScreenOn(true);
        //surfaceHolder.setFormat(PixelFormat.OPAQUE);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        isDrawing = true;
        mPath = new Path();
        paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(20);
        paint.setColor(Color.GREEN);
        paint.setPathEffect(new CornerPathEffect(10));
        paint.setAntiAlias(true);
        new Thread(this).start();
    }

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

    }

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        Log.e("onTouchEvent: ", "路径x=" + x);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mPath.moveTo(x, y);
                break;
            case MotionEvent.ACTION_MOVE:
                mPath.lineTo(x, y);
                break;
        }
        return true;
    }

    @Override
    public void run() {
        long start = System.currentTimeMillis();
        while (isDrawing) {
            draw();
        }
        long end = System.currentTimeMillis();
        //加上线程睡眠时间,防止太频繁的绘制
        if(end-start<=100){
            try {
                Thread.sleep(100-(end-start));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void draw() {
        try {
            //拿到绘图对象
            canvas = surfaceHolder.lockCanvas();
            canvas.drawColor(Color.WHITE);
            canvas.drawPath(mPath, paint);
            //绘制内容
        } catch (Exception e) {
            Log.e("draw: ", e.toString());
        } finally {
            //将绘图的内容提交
            surfaceHolder.unlockCanvasAndPost(canvas);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37321098/article/details/88244290