Android: Canvas.DrawBitmap VS Drawable.Draw - Huge performance boost

前端 未结 2 1167
没有蜡笔的小新
没有蜡笔的小新 2021-02-04 05:15

I just found out something and I was wondering about how and why. I\'m developing a small arcade game for Android. I decided to ignore OpenGL and use the standard SurfaceView an

相关标签:
2条回答
  • 2021-02-04 05:38

    Canvas.drawBitmap is doing a lot less work than Drawable.draw so it is faster.

    Drawable.draw

    Since Drawable is an abstract class, let's look at BitmapDrawable:

    BitmapDrawable.draw(canvas)

    public void draw(Canvas canvas) {
        final Bitmap bitmap = mBitmapState.mBitmap;
        if (bitmap == null) {
            return;
        }
        final BitmapState state = mBitmapState;
        final Paint paint = state.mPaint;
        if (state.mRebuildShader) {
            final Shader.TileMode tmx = state.mTileModeX;
            final Shader.TileMode tmy = state.mTileModeY;
            if (tmx == null && tmy == null) {
                paint.setShader(null);
            } else {
                paint.setShader(new BitmapShader(bitmap,
                        tmx == null ? Shader.TileMode.CLAMP : tmx,
                        tmy == null ? Shader.TileMode.CLAMP : tmy));
            }
            state.mRebuildShader = false;
        }
        final int restoreAlpha;
        if (state.mBaseAlpha != 1.0f) {
            final Paint p = getPaint();
            restoreAlpha = p.getAlpha();
            p.setAlpha((int) (restoreAlpha * state.mBaseAlpha + 0.5f));
        } else {
            restoreAlpha = -1;
        }
        final boolean clearColorFilter;
        if (mTintFilter != null && paint.getColorFilter() == null) {
            paint.setColorFilter(mTintFilter);
            clearColorFilter = true;
        } else {
            clearColorFilter = false;
        }
        updateDstRectAndInsetsIfDirty();
        final Shader shader = paint.getShader();
        final boolean needMirroring = needMirroring();
        if (shader == null) {
            if (needMirroring) {
                canvas.save();
                // Mirror the bitmap
                canvas.translate(mDstRect.right - mDstRect.left, 0);
                canvas.scale(-1.0f, 1.0f);
            }
            canvas.drawBitmap(bitmap, null, mDstRect, paint);
            if (needMirroring) {
                canvas.restore();
            }
        } else {
            updateShaderMatrix(bitmap, paint, shader, needMirroring);
            canvas.drawRect(mDstRect, paint);
        }
        if (clearColorFilter) {
            paint.setColorFilter(null);
        }
        if (restoreAlpha >= 0) {
            paint.setAlpha(restoreAlpha);
        }
    }
    

    You can see that it even calls canvas.drawBitmap internally.

    Canvas.drawBitmap

    Compare that to Canvas.drawBitmap. It is much shorter.

    Canvas.drawBitmap

    public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
        throwIfCannotDraw(bitmap);
        native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top,
                paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity, bitmap.mDensity);
    }
    

    There are a few different drawBitmap methods but all of them are shorter than the Drawable.draw method. Watch out for traps like this to keep your bitmap drawing fast.

    0 讨论(0)
  • 2021-02-04 05:39

    The SurfaceView of your Canvas is meant to be used when you should iterate constantly and Drawable is not for that purpose.

    0 讨论(0)
提交回复
热议问题