在CustomView中连续绘制时性能不佳

时间:2016-11-22 12:09:40

标签: android performance canvas surfaceview android-bitmap

使用案例

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

方法1

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

方法2

我创建了一个Bitmap,在将所有行绘制到另一个线程的位图后,我使用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并在另一个线程中对canvas对象执行所有操作。但由于SurfaceView使用CPU进行绘图操作,因此低配置手机的性能会很差。

任何人都可以指导我如何以更好的性能完成此任务吗?

2 个答案:

答案 0 :(得分:7)

可以使用方法1 来获得良好的效果。

听起来与您的用例相近的示例(绘制线条,一些文字并在手势移动时进行更新)是MPAndroidChart。这是一个实现高性能的开源库(如果需要统计数据,请参阅the following comparison

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

  1. 不要在渲染循环中分配。相反,在循环外部分配并重用/循环变量。请参阅LineChartRenderer line 199
  2. 使用缓冲。例如,在MPAndroidChart中,条形图中条形四个角的点被缓冲,缓冲区数组被重用。请参阅BarBuffer课程。
  3. 使用原生Canvas绘图功能(drawPathdrawLine等。)
  4. 可以在Android效果Slow Rendering Guide

    中找到有关优化渲染的完整提示列表

答案 1 :(得分:2)

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

ScreenBitmap是绘制到屏幕的内容 OffScreenBitmap用于在后台绘图。

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

创建这些位图一次(通常在onSizeChanged中),以便onDraw中没有任何配置