开发者

Why is algorithm so slow?

I'm creating a line graph, and the code I originally used was so slow at drawing that it was useless. I replaced it with code I found online and it became much faster. I was just curious as to why the original code is so slow. All of the code posted below is inside the onDraw() method of a custom view:

Original slow code:

    float yStart = 300f;

    for (int i=0; i < values.length; i++){              

        drawPath.moveTo(xStart, yStart);
        drawPath.lineTo(xStart+10, values[i]);
        drawPath.close();
        canvas.drawPath(drawPath, linePaint);

        xStart += 10;
        yStart = values[i]; 
    }

Later fa开发者_开发知识库st code:

            float datalength = values.length;
            float colwidth = (width - (2 * border)) / datalength;
            float halfcol = colwidth / 2;
            float lasth = 0;                
            for (int i = 0; i < values.length; i++) {
                float val = values[i] - min;
                float rat = val / diff;
                float h = graphHeight * rat;
                if (i > 0)
                    canvas.drawLine(((i - 1) * colwidth) + (horStart + 1) + halfcol, (border - lasth) + graphHeight, (i * colwidth) + (horStart + 1) + halfcol, (border - h) + graphHeight, linePaint);
                lasth = h;

I just don't understand why one is so much more efficient than the other. Any ideas?


It is CLEAR

In the first piece, there are three operations on objects {moveTo, lineTo, drawPath, and close}


Int the second piece, it is all float operations except one operation on objects


Using Paths makes the drawing significantly slower than simply telling the Canvas to draw a straight line between two points since Path is a much more complex object than the 2 points that drawLine() uses. Paths are also filled and framed based on the Style in the Paint which could also cause a slowdown.

In general, using objects and calling a lot of methods in a loop slows down your code.


After a bit of search, the problem probably came from where I said : you should only call moveTo for the first point of the graph, and then only call lineTo in the loop. When the path is defined entirely (after the for loop) you may draw it. The path is optimized for your purpose, but you where not using it correctly.

http://developer.android.com/reference/android/graphics/Path.html#lineTo%28float,%20float%29


I think you should do it like this:

float yStart = 300f;

drawPath.moveTo(xStart, yStart);

for (int i=0; i < values.length; i++){              
    drawPath.lineTo(xStart+10, values[i]);
    xStart += 10;
    yStart = values[i]; 
}

drawPath.close();

canvas.drawPath(drawPath, linePaint);

otherwise you will draw on the canvas the "building" of drawPath X times.

Also you can precalculate the path and have only the canvas.drawPath in the onDraw.


Also, you should use path.reset() to clear up the memory. Otherwise, every time you draw a different object using the same path it's gonna draw ALL of the objects you've drawn before using that path. So the complete code, would be.

float yStart = 300f;

drawPath.moveTo(xStart, yStart);

for (int i=0; i < values.length; i++){       
    drawPath.lineTo(xStart+10, values[i]);       
    xStart += 10;       
    yStart = values[i];
}

drawPath.close();

canvas.drawPath(drawPath, linePaint);

drawPath.reset();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜