2013-06-23 39 views
8

因此,我试图了解如何在自定义View中正确使用硬件加速(如果可用),并持续动画。这是我onDraw()的基本前提:在自定义视图中使用硬件层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()禁用它们,但我想知道我是否我真正使用它。本质上,调用drawBitmap()i/j循环从不改变;唯一改变的是Canvas翻译。 Bitmap是否在幕后自动保存到GPU中,或者是否有需要手动执行的操作?

+0

相反我可能误解了这个问题但你有没有设置'setLayerType(View.LAYER_TYPE_HARDWARE,null);'为你的视图? GPU只在用户正在进行滚动时才会缓存图像,但不会作为消耗较少资源的权衡。 – Slartibartfast

+0

@Slartibartfast是的,我已将图层类型设置为硬件。用户将永远不会滚动;视图不断滚动自己的内容。我可能误解了HW Acceleration,但我觉得我正在绘制的位图网格应该能够渲染到硬件层,并且只需转换而不是在每一帧上重新绘制位图。 – kcoppock

回答

6

您准确设置了View.LAYER_TYPE_HARDWARE什么样的视图?如果您在包含上面显示的绘图代码的视图上设置硬件层,则会导致系统执行大量的工作。既然你只绘制位图,你不需要在这里做任何事情。如果您致电Canvas.drawBitmap(),框架将代表您缓存由此产生的OpenGL纹理。

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

一般情况下,硬件层应该在意见认为是昂贵的画设定,其内容不会经常改变(所以相当多的你在做什么:)

+0

谢谢@RomainGuy。我在上面的View中设置了'LAYER_TYPE_HARDWARE'。所以纹理会自动缓存?这就是我一直在寻找的。所以你说,添加两个子视图并在这些子视图上使用翻译实际上更有效,而不是直接在画布上绘制位图?我会研究一下。谢谢! – kcoppock

+1

是的,纹理会自动缓存。您可以使用adb shell dumpsys gfxinfo com.your.app从命令行查询各种缓存的状态。在你的案例中使用Views *效率更高,因为你正在移动很多位图。我们使用Views来检测这种情况,而不是再次调用draw()方法,我们只是在渲染器内部设置本地属性。它几乎是免费的。 –

1

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

developer.android.com

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

还有一个教程的Android Performance Study由罗曼盖伊描述它的使用几乎一步一步来。

相关问题