2011-08-01 12 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

私は他の人にそれに答えるようにします。 – Idistic

+0

'line'を描画するのに' path'を使うのはあまり効率が悪いかもしれません。パスは、最後に描画する場合、forループの後に効率的でした。forループの後にのみdrawPathを呼び出そうとし、lineToを呼び出すことはできますか? –

答えて

1

Pathを使用すると、Canvasに2点間に直線を描画するように指示するよりも大幅に遅くなりますは、drawLine()が使用する2つのポイントよりはるかに複雑なオブジェクトです。 PathPaintStyleに基づいて塗りつぶされ額縁化されており、これも減速の原因となる可能性があります。

一般に、オブジェクトを使用してループ内で多くのメソッドを呼び出すと、コードが遅くなります。

+0

描画に使用されているアルゴリズムを示すリソースはありますか? (例えば 'Canvas.drawLine' - >' Bresenham'、 'Canvas.drawCircle' - >' MidPoint'など)私は 'NDK'を検索していましたが、残念ながらこの知識を得る方法はありません。 –

2

それは最初のピースでCLEAR

で、オブジェクト{のmoveTo、のlineTo、drawPath、及び近い}第二片のInt


上の3つの操作があり、それはすべてのフロートでありますオブジェクトに対する1つの操作を除いた操作

1

少しの検索の後で、問題はおそらく私が言ったところから来たのでしょう:あなたはグラフの最初の点についてmoveToを呼び出し、ループ内でlineToだけを呼び出すべきです。パスが完全に定義されているとき(forループの後に)、それを描画することができます。パスは目的に合わせて最適化されていますが、正しく使用されていない場所です。

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

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()を使用する必要があります。それ以外の場合は、同じパスを使用して別のオブジェクトを描画するたびに、そのパスを使用する前に描画したすべてのオブジェクトを描画します。だから、完全なコードは、そうだろう。私は専門家(各パスは、他の経路(単数または複数)に関連して計算されなければならない?)パスのN番号を実行することによって発生キャンバスクリッピングが何らかの方法でより高価な、おそらく添加剤ではない疑い

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(); 
関連する問題