【问题标题】:Bad performance when drawing continuously in CustomView在 CustomView 中连续绘制时性能不佳
【发布时间】:2017-04-06 02:31:35
【问题描述】:

用例:

我需要在我的视图上画一百行和几段文字。我需要提供滚动效果,为此我捕获ACTION_MOVE 事件并用更新的点重新绘制所有线条。为了得到想要的结果,我尝试了不同的方法,但没有一个按预期工作。

方法 1

我创建了一个扩展 View 的自定义类。所有的绘图和计算都直接在我的onDraw() 方法中完成。由于在onDraw() 方法中完成了很多操作,因此应用程序的性能很差。我什至使用 Profile GPU 渲染 检查了性能,我可以看到线条非常高。

方法 2

我创建了一个位图,在另一个线程中将所有线条绘制到我的位图上后,我使用postInvalidate()onDraw() 方法中绘制位图:

mBufferedBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);   
mBufferedBitmap.eraseColor(Color.TRANSPARENT);    
Canvas mBufferedCanvas = new Canvas(mBufferedBitmap);               
drawLines(mBufferedCanvas)    
postInvalidate();

由于我擦除了位图上所有以前的绘图并使用更新的点绘制新线,因此屏幕上出现了闪烁。

方法 3

我尝试将我的自定义类扩展到SurfaceView 并在另一个线程中对画布对象执行所有操作。但是由于SurfaceView使用CPU进行绘图操作,所以在低配置的手机上性能会很差。

谁能指导我如何以更好的性能完成这项任务?

【问题讨论】:

  • 尝试查看RenderScript。我自己没有使用过该框架,但这似乎是一个很好的用例。
  • 我的用例不需要 RenderScript。
  • 不要在onDraw()分配新的位图,这就是你有fps下降的原因。
  • 不要使用位图操作,如果只有线条,您可以使用视图本身来实现。

标签: android performance canvas surfaceview android-bitmap


【解决方案1】:

可以使用您的方法 1 来获得良好的性能。

MPAndroidChart 是一个听起来与您的用例相近的示例(画线、少量文本以及对手势移动进行这些更新)。这是一个实现高性能的开源库(如果需要统计信息,请参阅the following comparison

要检查的类是 Renderer 类,因为它们包含图表子类型的 onDraw(Canvas c) 中的代码绘制。您可以在那里看到一些用于实现高性能的技巧:

  1. 不要在渲染循环中分配。相反,在循环外分配并重用/回收变量。见LineChartRendererline 199
  2. 使用缓冲。例如,在 MPAndroidChart 中,对条形图中条形的四个角点进行缓冲,并重复使用缓冲区数组。请参阅 BarBuffer 类。
  3. 使用原生的Canvas绘图函数(drawPathdrawLine等)

可在 Android 性能Slow Rendering Guide 中找到优化渲染技巧的完整列表

【讨论】:

    【解决方案2】:

    方法 2 是最好的方法。如果您看到闪烁,这意味着位图在您擦除它之后且在您绘制所有线条之前被绘制到屏幕上。如果是这种情况,请使用另一个位图并进行双缓冲:

    ScreenBitmap 是在屏幕上绘制的 OffScreenBitmap 用于在后台绘制。

    将所有线条和文本绘制到 OffScreenBitmap,完成后,将其复制到 ScreenBitmap。 在 onDraw 中,绘制 ScreenBitmap。

    创建这些位图一次(通常在 onSizeChanged 中),这样在 onDraw 中就没有分配

    【讨论】:

      猜你喜欢
      • 2021-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-26
      相关资源
      最近更新 更多