2011-08-01 98 views
3

我創建了一個線條圖,我原來使用的代碼在繪圖時非常慢,以至於沒用。我用我在網上找到的代碼替換它,它變得更快。我只是好奇爲什麼原始代碼太慢。所有貼在下面的代碼是一個自定義視圖的的onDraw()方法中:算法爲什麼這麼慢?

原始慢碼

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]; 
    } 

後來快速的代碼

  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; 

我只是不明白爲什麼一個比另一個更有效率。有任何想法嗎?

+0

我懷疑通過運行路徑N個數發生的畫布剪裁是更昂貴的並且可能添加劑以某種方式(每個路徑具有相對於其它路徑(多個)被計算的?)不上的專家路徑的內部,所以我會讓其他人回答。 – Idistic

+0

也許使用'path'繪製'line'效率較低。如果你只在最後,在for循環之後進行繪製,那麼路徑將會很有效率。您是否可以嘗試在for循環之後調用drawPath,並只調用lineTo? –

回答

1

使用Path s使繪圖比簡單地告訴Canvas在兩點之間劃一條直線從Path是一個比drawLine()使用的2點更復雜的對象。 Path也會根據Paint中的Style進行填充和加框,這也會導致放緩。

通常,使用對象並在循環中調用很多方法會減慢代碼的速度。

+0

是否有任何資源提及用於繪圖的算法? (例如'Canvas.drawLine' - >'Bresenham','Canvas.drawCircle' - >'MidPoint'等)。我一直在搜索'NDK',但不幸的是我無法找到獲取這種知識的方法。 –

2

它是CLEAR

在第一片,上有對象{的moveTo,了lineTo,drawPath,並關閉}


詮釋第二部件3點的操作,它是所有浮除了對象上的一個操作之外的操作

1

我認爲你應該做這樣的:

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 X次 「建築」。

此外,您可以預先計算路徑,並只有onDraw中的canvas.drawPath。

+0

我其實已經試過了。它的運行速度比原始代碼快,但仍然非常慢。 – user650309

0

另外,您應該使用path.reset()清除內存。否則,每次使用相同的路徑繪製不同的對象時,它會在使用該路徑之前繪製所有繪製的對象。所以完整的代碼將會是。

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();