Android:Canvas.DrawBitmap VS Drawable.Draw - 巨大的性能提升

时间:2010-11-28 11:07:05

标签: android

我刚发现了一些东西,我想知道如何以及为什么。 我正在为Android开发一款小型街机游戏。我决定忽略OpenGL并使用标准的SurfaceView和Drawables来做它,因为它假设很轻(10个精灵左右)。 我有加载的drawable,我使用Draw方法并将它们传递给我的画布。这是每个精灵如何绘制到屏幕上的。 事实证明,绘制4-5个大精灵(200X400左右)需要花费很长时间才能使用不那么全新的手机型号。足够长的时间让我的游戏无法播放。我们谈论使用这种方法绘制单帧的时间为50-60毫秒。除了画画之外我真的不做任何事情,无处可削减成本。所以我决定尝试使用Bitmaps。但是,我需要预先设置大小,因为位图中没有'setBounds'方法。没问题,我调整它们以适应当前屏幕的负载,问题解决了。

行。所以我得到了位图。我现在使用Canvas.DrawBitmap进行绘制。我采用了新的绘制方法......我得到了一个强烈的 400%的性能提升!而不是50-60ms,整个绘制循环现在需要8-12ms。 到底是什么? 为了排除它,我也计时了setBounds,它需要< 1ms所以它不应该受到责备。这是实际的Drawable.Draw,减慢了速度。

对我来说这是个好消息,因为我真的不想学习OpenGL来让我的游戏可玩,但我不禁想知道它 - 它没事吗?我的方法有问题吗?为什么不在任何地方提到它?

2 个答案:

答案 0 :(得分:4)

SurfaceView的{​​{1}}意味着在您应该不断迭代并且Canvas不是为此目的时使用。

答案 1 :(得分:1)

Canvas.drawBitmap的工作量远远少于Drawable.draw,因此速度更快。

Drawable.draw

由于Drawable是一个抽象类,让我们看一下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);
    }
}

您可以看到它甚至在内部调用canvas.drawBitmap

Canvas.drawBitmap

将其与Canvas.drawBitmap进行比较。它要短得多。

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);
}

有一些不同的drawBitmap方法,但它们都比Drawable.draw方法短。注意陷阱like this以保持位图快速绘制。