8

因此,我试图了解如何在View持续动画的自定义中正确使用硬件加速(如果可用)。这是我的基本前提onDraw()

canvas.drawColor(mBackgroundColor);

for (Layer layer : mLayers) {
    canvas.save();
    canvas.translate(layer.x, layer.y);

    //Draw that number of images in a grid, offset by -1
    for (int i = -1; i < layer.xCount - 1; i++) {
        for (int j = -1; j < layer.yCount - 1; j++) {
            canvas.drawBitmap(layer.bitmap, layer.w * i, layer.h * j, null);
        }
    }

    //If the layer's x has moved past its width, reset back to a seamless position
    layer.x += ((difference * layer.xSpeed) / 1000f);
    float xOverlap = layer.x % layer.w;
    if (xOverlap > 0) {
        layer.x = xOverlap;
    }

    //If the layer's y has moved past its height, reset back to a seamless position
    layer.y += ((difference * layer.ySpeed) / 1000f);
    float yOverlap = layer.y % layer.h;
    if (yOverlap > 0) {
        layer.y = yOverlap;
    }

    canvas.restore();
}

//Redraw the view
ViewCompat.postInvalidateOnAnimation(this);

我正在启用硬件层并在 中onAttachedToWindow()禁用它们onDetachedFromWindow(),但我试图了解我是否真的在使用它。本质上,i/j调用的循环drawBitmap()永远不会改变;唯一改变的是Canvas翻译。是在Bitmap幕后作为纹理自动保存到 GPU,还是我需要手动执行一些操作?

4

2 回答 2

7

你到底在什么视图上设置View.LAYER_TYPE_HARDWARE?如果您在包含上面显示的绘图代码的视图上设置硬件层,您会导致系统做的工作比必要的多得多。由于您只绘制位图,因此您无需在此处执行任何操作。如果您调用Canvas.drawBitmap()框架将代表您缓存生成的 OpenGL 纹理。

但是,您可以进一步优化您的代码。drawBitmap()您可以使用子视图,而不是调用。如果您使用offset*()方法(或setX()/ setY())移动这些子项,则框架将应用进一步的优化以避免draw()再次调用这些方法。

一般来说,硬件层应该设置在绘制成本高且内容不会经常改变的视图上(这与你正在做的事情几乎相反:)

于 2013-07-01T22:30:38.107 回答
1

您可以使用 Android 的Tracer for OpenGL ES来查看您的视图是否发出 OpenGL 命令。

来自developer.android.com

Tracer 是一款用于分析 Android 应用程序中的嵌入式系统 (ES) 代码的 OpenGL 工具。该工具允许您捕获 OpenGL ES 命令和逐帧图像,以帮助您了解图形命令的执行方式。

Romain Guy还有一个关于Android 性能研究的教程,它几乎一步一步地描述了它的使用。

于 2013-07-01T12:27:45.680 回答