在自定义视图onDraw中使用硬件层

时间:2013-06-23 05:41:44

标签: android performance android-view hardware-acceleration

所以我试图了解如何在持久动画的自定义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的{​​{1}}循环永远不会改变;唯一改变的是drawBitmap()翻译。 Canvas是否会在幕后自动保存到GPU中,或者我需要手动执行此操作吗?

2 个答案:

答案 0 :(得分:6)

您在哪个视图中准确设置了View.LAYER_TYPE_HARDWARE?如果要在包含上面显示的绘图代码的视图上设置硬件层,则会导致系统执行大量必要的工作。由于您只是绘制位图,因此您无需在此处执行任何操作。如果您调用Canvas.drawBitmap(),框架将代表您缓存生成的OpenGL纹理。

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

一般情况下,应该在视图上设置硬件图层,这些视图的绘制成本很高,而且其内容不会经常更改(所以与您正在做的事情完全相反:)

答案 1 :(得分:1)

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

来自developer.android.com

  
    

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

  

Romain Guy还有一个关于Android Performance Study的教程,它逐步描述了它的用法。