[android游戏开发初学]SurfaceView初探之缓冲区测试

先上测试代码

private static class PathView extends SurfaceView implements SurfaceHolder.Callback{
        private int vWidth;
        private int vHeight;
        private Paint pPaint;
        private Path mPath;
        private float endX;
        private float endY;
        private Random random;
        DrawThread dt;
        public PathView(Context context) {
            super(context);
            pPaint = new Paint();
            pPaint.setAntiAlias(true);
            pPaint.setColor(0xaf22aa22);
            pPaint.setStyle(Paint.Style.STROKE);
            mPath = new Path();
            random = new Random();
            getHolder().addCallback(this);
        }
        
        private void  init(){
            vWidth = getWidth();
            vHeight = getHeight();
            endX = 0.8f*vWidth;
            endY = 0.8f*vHeight;
        }
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            init();
            dt = new DrawThread();
            dt.runflag = true;
            dt.start();
        }
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                int height) {
            init();
        }
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            dt.runflag = false;
            dt = null;
        }
        public void doDraw(Canvas canvas){
            clear(canvas);
            canvas.drawPath(mPath, pPaint);
        }
        public boolean processing(){
            //这里构建贝塞尔曲线
            mPath.reset();
            mPath.moveTo(50, 50);
            mPath.quadTo(random.nextInt(vWidth), random.nextInt(vHeight), endX/2, random.nextInt(vHeight));
            mPath.quadTo(random.nextInt(vWidth), random.nextInt(vHeight), endX, endY);
            return true;
        }
        // 缓存debug的相关的参数
        private int ind = 0;
        private boolean DEBUG_BUFFER = true;
        private void clear(Canvas canvas) {
            int color = Color.BLACK;
            if(DEBUG_BUFFER){
                if(ind==0){
                    color = Color.RED;
                }else if(ind==1){
                    color=Color.GREEN;
                }else if(ind==2){
                    color = Color.BLACK;
                }else if(ind==3){
                    color = Color.WHITE;
                }else{
                    //ind>3 之后不清屏,查看绘制状态
                    return;
                }
                ind++;
            }
            canvas.drawColor(color);
        }
        //刷新线程
        class DrawThread extends Thread{
            private boolean runflag = false;
            @Override
            public void run() {
                while (runflag) {
                    try {
                        loop();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
            void loop() throws InterruptedException{
                processing();
                Canvas canvas = null;
                try {
                    canvas = getHolder().lockCanvas();
                    if(canvas!=null){
                        doDraw(canvas);
                    }
                }catch (Exception e) {
                    
                }finally{
                    if(canvas!=null){
                        getHolder().unlockCanvasAndPost(canvas);
                    }
                }
                Thread.sleep(500);
            }
        }
    }


正常情况下,显示效果是不断的显示不同的贝塞尔曲线。但是如果没有做清屏操作的话,会不停的在原有的基础上进行绘制

 
这里注意一下 clear 方法
private void clear(Canvas canvas) {
            int color = Color.BLACK;
            if(DEBUG_BUFFER){
                if(ind==0){
                    color = Color.RED;
                }else if(ind==1){
                    color=Color.GREEN;
                }else if(ind==2){
                    color = Color.BLACK;
                }else if(ind==3){
                    color = Color.WHITE;
                }else{
                    //ind>3 之后不清屏,查看绘制状态
                    return;
                }
                ind++;
            }
            canvas.drawColor(color);
}

 
这个方法,如果设置了 DEBUG_BUFFER 为true来debug缓冲区的话,会在前四帧分别设置不同的背景色。而在ind>3之后,不再做清屏操作。
如果按正常逻辑的,ind>3之后背景色会一直是最后一次即ind==3时候设置的颜色
但测试结果是,当指示器 ind >3之后,前后刷屏显示的颜色竟然是ind=3和ind==2设置的两个颜色之间切换
由此可推断出本人所使用的测试机为两块缓冲区。后来又进行了一些测试,有的机型会有四块缓冲区或者更多。
因此,前边提到的“但是如果没有做清屏操作的话,会不停的在原有的基础上进行绘制”指的是对应缓冲区基础上的绘制。也就是说,两片缓冲区绘制的内容都是不完整的
 
所以,要使用SurfaceView,如果没有特殊需求必须在每次绘制之前清屏,把所有需要绘制的东西再全部绘制一次,才会获取到想要的效果。 当然,在适当的时候,也可以加上一个BItmap做缓冲,而不用记录之前已绘制的状态。
原文地址:https://www.cnblogs.com/boliu/p/3307607.html