【问题标题】:Partial invalidation in custom Android view with hardware acceleration使用硬件加速的自定义 Android 视图中的部分失效
【发布时间】:2011-08-29 17:53:55
【问题描述】:

我的应用程序中有一个自定义视图,它填充了整个活动。

在大多数情况下,当我想刷新控件时,我会调用invalidate(),不带任何参数。

但是,在某些情况下,如果我只更改控件的一小部分区域,我会调用 invalidate(Rect) 以避免重绘整个屏幕。这很重要,因为在这些情况下,我 需要尽快更新。

这似乎工作正常,但是,当我在 Honeycomb 中启用硬件加速(即在 AndroidManifest.xml 中设置android:hardwareAccelerated="true")时,部分重绘似乎不起作用。

如果我在我的onDraw() 方法中执行Log.d("FOO", canvas.getClipBounds()),就可以看到这一点;输出只是显示整个控件正在更新,而在禁用硬件加速的情况下,我得到了正确的输出区域。

在使用硬件加速时,有什么方法可以使部分失效工作?

非常感谢,马特

【问题讨论】:

  • 我也一直在想这个问题,并且遇到了与您描述的相同的结果。您对在使用硬件加速时尝试使部分失效起作用有任何更新吗?或者关于为什么这不起作用的任何更新?
  • 部分更新有效。显示列表必须包含视图的所有绘制命令,但只有与脏区相交的命令才会真正执行。

标签: android


【解决方案1】:

部分重绘工作正常,只有屏幕的指定区域会被重绘。然而,它不会改变 Canvas 上的剪辑边界。所有的绘制操作都会被记录下来,但只有那些与脏区相交的操作才会真正被执行。

更新:从 Lollipop (API 21) 开始,部分失效发生在视图级别(即,您不能使少于整个视图失效)。

【讨论】:

  • 不,我有同样的问题。通过硬件加速,onDraw(Canvas canvas)canvas.getClipBound() 返回整个视图的区域。而在没有硬件加速的情况下,canvas.getClipBound() 返回正确的脏矩形。我认为这可能取决于设备。
  • 对不起,我做了一个实验。在我看来的onDraw(Canvas canvas),它画了一个长的Path,我用一个小的Rect 无效。通过硬件加速,它绘制了整个路径。在没有硬件加速的情况下,它只绘制Rect 内的部分。
  • 通过硬件加速,只有脏矩形内的部分会被绘制。你的测试到底是什么?你如何验证结果? Fwiw,我写了这个渲染管道:)
  • 借助硬件加速,我们会在多种情况下强制重绘整个窗口,包括恢复 Activity。然而,这并不意味着脏区总是被忽略。您可以通过在设置 > 开发人员选项中打开 GPU 视图更新来验证这一点。更新窗口时屏幕会闪烁红色。
  • 根据我的硬件加速经验,整个视图总是被重绘。我已经通过将视图拆分为较小视图的网格并仅使更改的视图无效来验证了这一点。在这种情况下,性能得到了很大改善。
【解决方案2】:

启用 HA 后,渲染管线将使用DisplayList 来存储绘图命令。即使你在View.invalidate 中指定了脏区,整个 displaylist 也会被重建(想想我们怎么能只更新一小部分的DisplayList,这是不可能的吧?)。最终,作为@Romain 说,只有真正的脏区会被重绘。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-15
    相关资源
    最近更新 更多