Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bad performance when drawing continuously in CustomView

Use case:

I need to draw hundred lines and a few pieces of text on my view. I need to give a scrolling effect, for which I capture the ACTION_MOVE event and redraw all the lines with the updated points. To get the desire result I tried with different approaches but none works as intended.

Approach 1

I made a custom class which extends View. All the drawing and calculation is done directly in my onDraw() method. Since there is so much of operation done in onDraw() method, the performance of the app is very poor. I even checked the performance using Profile GPU rendering and I can see the lines are very tall.

Approach 2

I created a Bitmap and after drawing all the lines onto my bitmap in another thread, I used postInvalidate() to draw the bitmap in onDraw() method:

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

Since I erase all the previous drawing on the bitmap and draw new lines with updated points, there is a flickering on the screen.

Approach 3

I tried extending my custom class to SurfaceView and performing all the operations on canvas object in another thread. But since SurfaceView uses CPU for drawing operations, the performance will be poor in low configuration mobiles.

Can anyone guide me how to achieve this task with better performance?

like image 499
VijayRaj Avatar asked Nov 22 '16 12:11

VijayRaj


1 Answers

It is possible to use your approach 1 to achieve good performance.

An example that sounds close to your use case (drawing lines, a little text and having these update on gesture movement) is MPAndroidChart. This is an open source library that achieves high performance (see the following comparison if you want stats)

The classes to examine are the Renderer classes as these contain code draw in the onDraw(Canvas c) of the chart subtypes. You can see some of the tricks used to achieve high performance there:

  1. Don't allocate in a render loop. Instead, allocate outside the loop and reuse/recycle variables. See LineChartRenderer line 199
  2. Use buffering. For example, in MPAndroidChart, the points for the four corners of the bars in the bar chart are buffered and the buffer array is reused. See the BarBuffer class.
  3. Use the native Canvas drawing functions (drawPath, drawLine etc.)

A complete list of tips for optimising rendering can be found in the Android Performance Slow Rendering Guide

like image 195
David Rawson Avatar answered Oct 13 '22 23:10

David Rawson