安卓-SurfaceView

一、SurfaceView是View的孪生兄弟

View通过刷新来重绘视图,安卓系统通过发出VSYNC信号来进行屏幕重绘,刷新间隔是16ms。如果一次重绘耗时太长超过16ms会出现警告的log告诉你主线程可能做太多事情

SurfaceView的刷新是被动的,我们让他刷新的时候才执行刷新操作。并且SurfaceView使用了双缓冲而View没有

 

二、SurfaceView的使用

SurfaceView可以使用模板进行编写,这里做了一个模板如下所示

public abstract class SurfaceViewTemplate extends SurfaceView implements SurfaceHolder.Callback, Runnable {

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

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

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

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

    protected SurfaceHolder mHolder;
    protected void initView(Context context) {
        mHolder = getHolder();
        mHolder.addCallback(this);
        setFocusable(true);
        setKeepScreenOn(true);
        setFocusableInTouchMode(true);
    }

    boolean mIsDrawing;
    @Override
    public void surfaceCreated(@NonNull SurfaceHolder holder) {
        mIsDrawing = true;
        new Thread(this).start(); // 开线程出来进行绘制操作
    }

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

    }

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

    private final long DRAW_DURATION = 50;
    @Override
    public void run() {
        while (mIsDrawing) {
            long startTime = System.currentTimeMillis();
            drawSurface();
            long endTime = System.currentTimeMillis();
            if (endTime - startTime < DRAW_DURATION) { // 让drawSurface每50毫秒刷一次,低于50毫秒则通过sleep把资源让出来
                try {
                    Thread.sleep(DRAW_DURATION - (endTime - startTime));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void drawSurface() {
        Canvas canvas = null;
        try {
            canvas = mHolder.lockCanvas(); // 获取画布,并在该画布上面进行绘制
            if (canvas != null) {
                drawSurface(canvas);
            }
        } catch (Exception e) {

        } finally {
            if (canvas != null) {
                mHolder.unlockCanvasAndPost(canvas); // 将画布的内容进行提交
            }
        }
    }

    /**
     * 让子类实现该方法来执行绘图操作
     * */
    protected abstract void drawSurface(Canvas canvas);
}

 

三、使用二模板实现一个动态绘制正弦图的例子

    private Path mPath;
    private Paint mPaint;
    @Override
    protected void initView(Context context) { // 继承父类的initView进行初始化
        super.initView(context);

        mPath = new Path();
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.BLACK);
        mPaint.setStrokeWidth(10);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
    }

    @Override
    public void surfaceCreated(@NonNull SurfaceHolder holder) {
        mPath.moveTo(0, 400);
        super.surfaceCreated(holder);
    }

    private int x = 0;
    private int y = 0;
    @Override
    protected void drawSurface(Canvas canvas) { // 继承父类的drawSurface进行绘制想要的图
        canvas.drawColor(Color.WHITE);
        canvas.drawPath(mPath, mPaint);

        x += 1;
        y = (int) (100 * Math.sin(x * Math.PI / 180) + 400);
        mPath.lineTo(x, y);
    }

 

posted @ 2023-01-05 09:04  LCAC  阅读(273)  评论(0)    收藏  举报