双缓冲,画布以高更新速率闪烁

时间:2017-03-05 17:59:50

标签: java android multithreading canvas bitmap

我开发了一个类来在后台Bitmap中呈现Thread,而主线程在屏幕上显示另一个Bitmap。渲染完成后,位图将被切换。

工作就像一个确定更新率的魅力(约+/- 50ms);但是当我需要更多帧时,我会看到一个闪烁的屏幕。

允许使用SurfaceView,我想避免使用同步机制......

目前我正在使用3个缓冲区进行渲染,很有希望,但我想避免使用大量内存。

有什么想法吗?

我的渲染课程" 50ms更新率"

说明:调用方法fireRender时,将清除辅助(辅助)位图,并在其上执行新的绘制。绘制后,位图将被交换。

public abstract class Render {
    private final Bitmap[] mBitmaps = new Bitmap[2];
    private final Canvas mCanvas = new Canvas();
    private int mRendered = 0, mAuxiliar = 1;
    protected final int mWidth, mHeight;

    public Render(int width, int height) {
        mWidth = width;
        mHeight = height;
        mBitmaps[0] = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        mBitmaps[1] = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    }

    private void preRender() {
        int aux = mAuxiliar;
        mCanvas.setBitmap(mBitmaps[aux]);
        mBitmaps[aux].eraseColor(0);
    }

    private void postRender() {
        int aux = mRendered;
        mRendered = mAuxiliar;
        mAuxiliar = aux;
    }

    public void fireRender() {
        preRender();
        onRender(mCanvas);
        postRender();
    }

    public void draw(Canvas canvas, int x, int y) {
        canvas.drawBitmap(mBitmaps[mRendered], x, y, null);
    }

    protected abstract void onRender(Canvas canvas);
}

这个迷你Activity类使用它

说明:

PathRender生成一个随机路径,仅用于说明我的问题。

View类CustomView绘制一个Render对象。

Timer负责"更新"。

public class MainActivity extends Activity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final int UPDATE_RATE = 20; // milliseconds

        final PathRender pathRender = new PathRender(1024, 512);
        final CustomView view = new CustomView(this, pathRender);
        setContentView(view);

        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                pathRender.fireRender();
                view.postInvalidate();
            }
        }, 0, UPDATE_RATE);

    }

    // Renders a random Path
    private static class PathRender extends Render {
        private final Path mPath = new Path();
        private final Paint mPaint = new Paint();

        public PathRender(int width, int height) {
            super(width, height);
            mPaint.setColor(Color.RED);
            mPaint.setStrokeWidth(2);
            mPaint.setStyle(Paint.Style.STROKE);
        }

        @Override
        protected void onRender(Canvas canvas) {
            Path p = mPath;
            p.rewind();
            p.moveTo(0, mHeight);

            Random r = new Random();
            for (int i=1; i<mWidth; i += 4) {
                p.lineTo(i, r.nextInt(mHeight));
            }
            p.lineTo(mWidth, mHeight);
            p.close();

            canvas.drawPath(p, mPaint);
        }
    }

    private static class CustomView extends View {
        private final Render mRender;

        public CustomView(Context context, Render render) {
            super(context);
            mRender = render;
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            mRender.draw(canvas, 0, 0);
        }
    }
}

修改

在20ms更新速率下发生的情况(例如) - 图像闪烁。

Flickering (20ms)

我希望在20ms时发生 - 图像为50ms(没有闪烁)。

Not flickering (50ms)

1 个答案:

答案 0 :(得分:0)

我用3个缓冲区解决了这个问题。这不是我想要的,但闪烁得到了解决。

观察:我将更新率更改为5毫秒,并且出现了闪烁。所以我又添加了一个缓冲区,它又恢复了工作。