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

Android 在自定义视图onDraw中使用硬件层,android,performance,android-view,hardware-acceleration,Android,Performance,Android View,Hardware Acceleration,因此,我试图了解如何在持续动画化的自定义视图中正确使用硬件加速(如果可用)。这是我的onDraw()的基本前提: canvas.drawColor(mBackgroundColor); 用于(图层:多层){ canvas.save(); canvas.translate(layer.x,layer.y); //在网格中绘制该数量的图像,偏移-1 对于(int i=-1;i0){ 第y层=yOverlap; } canvas.restore(); } //重新绘制视图 ViewCompat.pos

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

canvas.drawColor(mBackgroundColor);
用于(图层:多层){
canvas.save();
canvas.translate(layer.x,layer.y);
//在网格中绘制该数量的图像,偏移-1
对于(int i=-1;i0){
层x=xOverlap;
}
//如果层的y移动超过其高度,请重置回无缝位置
层y+=((差*层y速度)/1000f);
浮动y重叠=层y%层h;
如果(yOverlap>0){
第y层=yOverlap;
}
canvas.restore();
}
//重新绘制视图
ViewCompat.postInvalidateOnAnimation(此);
我在
onAttachedToWindow()
中启用硬件层,并在
OnAttachedFromWindow()
中禁用它们,但我试图了解我是否在实际使用它。本质上,调用
drawBitmap()
i/j
循环从未改变;唯一改变的是
画布
翻译。位图是否会在后台自动保存到GPU作为纹理,或者是否需要手动执行某些操作?

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

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

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

您正在设置什么视图
视图。层类型硬件
?如果要在包含上述图形代码的视图上设置硬件图层,则会导致系统执行比所需更多的工作。由于您只绘制位图,因此无需在此处执行任何操作。如果调用
Canvas.drawBitmap()
,框架将代表您缓存生成的OpenGL纹理

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


一般来说,硬件层应设置在绘制成本较高且内容不会经常更改的视图上(与您的操作完全相反:)

我可能误解了这个问题,但您是否设置了
setLayerType(View.LAYER\u TYPE\u hardware,null)用于您的视图?GPU只会在用户处于活动滚动状态时缓存图像,而不会在其他情况下缓存图像,作为消耗较少资源的权衡。@Slartibartfast是的,我已将层类型设置为硬件。用户永远不会真正滚动;视图不断滚动自己的内容。我可能误解了硬件加速,但我觉得我正在绘制的位图网格应该能够被渲染到硬件层中,并进行转换,而不是在每一帧上重新绘制位图。谢谢@RomainGuy。我在上面显示的
视图上设置
图层类型硬件
。那么纹理将自动缓存?这就是我要找的。你是说添加两个子视图并在这些子视图上使用翻译比直接在画布上绘制位图更有效?我会调查的。谢谢是,纹理将自动缓存。您可以使用adb shell dumpsys gfxinfo com.your.app从命令行查询各种缓存的状态。在您的案例中使用视图更有效,因为您经常移动位图。我们通过视图检测到这种情况,不再调用draw()方法,而是在渲染器内部设置本机属性。几乎是免费的。
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);