安卓-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 @   LCAC  阅读(260)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示