【问题标题】:Efficient onDraw of ArrayListArrayList的高效onDraw
【发布时间】:2012-04-18 20:57:32
【问题描述】:

我有一个自定义视图,我在其上绘制了一个坐标 ArrayList(这是一个仅包含 x 和 y 位置的自定义类)。随着越来越多的坐标被添加到 ArrayList 中,绘图速度明显变慢。我想知道是否有一种更有效的方法来绘制这个 ArrayList,或者,如果我可以只添加一个已添加的坐标(因为 ArrayList 只在调用无效之间更改一个坐标)。

以下是相关代码:

public class CustomDraw extends View {
// member variables

public void updateLine() {
    // grab new coordinates for each measure

    if(measure1.isEmpty()) {
        measure1.add(new Coordinate(0, 0));
    } else {
        Coordinate last_coord = measure1.get(measure1.size() - 1);

        // calculations for south, north, east, and west

        if(south && east) {
            measure1.add(new Coordinate(last_coord.x + 3, last_coord.y + 3));
        } else if(south && west) {
            measure1.add(new Coordinate(last_coord.x - 3, last_coord.y + 3));
        } else if(north && east) {
            measure1.add(new Coordinate(last_coord.x + 3, last_coord.y - 3));
        } else if(north && west) {
            measure1.add(new Coordinate(last_coord.x - 3, last_coord.y - 3));
        }
    }

    if(draw) {
        dh.sleep(10);
    }
}


@Override
public void onDraw(Canvas c) {
    super.onDraw(c);
    Paint p = new Paint();
    p.setStyle(Paint.Style.FILL);

    p.setColor(Color.WHITE);
    c.drawPaint(p);
    p.setColor(Color.BLACK);

    switch(mSelected) {
    case Constants.MEASURE_1:
        for(int i = 0; i < measure1.size(); i++) {
            Coordinate coord = measure1.get(i);
            Log.d("MAAV", "drawing coord.x, coord.y: " + (coord.x) + ", " + (coord.y));
            c.drawRect(coord.x, coord.y, coord.x + 3, coord.y + 3, p);  
        }
        break;
    }

}

class DrawHandler extends Handler {

    @Override
    public void handleMessage(Message msg) {
        CustomDraw.this.updateLine();
        CustomDraw.this.invalidate();
    }

    public void sleep(long delayMillis) {
        this.removeMessages(0);
        sendMessageDelayed(obtainMessage(0), delayMillis);
    }
}
}

感谢您的帮助!

【问题讨论】:

    标签: android arraylist android-canvas android-custom-view


    【解决方案1】:

    您在循环的每次迭代中声明coord。您不需要这样做,并且为对象分配内存可能会很昂贵。将其移出循环并简单地重用该对象。还可以尝试注释掉日志调用或仅记录每 10 项。

    Coordinate coord;
    for(int i = 0; i < measure1.size(); i++) {
       coord = measure1.get(i) 
       if (i%10==0)
           Log.d("MAAV", "drawing coord.x, coord.y: " + (coord.x) + ", " + (coord.y));
       c.drawRect(coord.x, coord.y, coord.x + 3, coord.y + 3, p);  
    }
    

    如果这些更新不能充分提高性能,请考虑使用 OpenGL ES 进行绘图。

    【讨论】:

      【解决方案2】:

      除了 slayton 建议的改进之外,使用 HashSet 代替 ArrayList 也可能是可行的。这样您将无法添加重复的坐标。我不知道你是否这样做,但如果你这样做,这种改进会减少迭代。

      如果你选择这样做,你需要为你的 Coordinate 类实现一个 equals 方法,我相信你知道。或者你也可以使用 java Point 类,如果你的坐标只保存 x 和 y 位置。

      【讨论】:

      • 感谢您的建议。我一定会调查的。
      【解决方案3】:

      我的方法是在每个 onDraw 上在位图中绘制您的画布(或者使用 ImageView 的扩展并使用 backgroundDrawable)。向您的类添加一个字段以保存最新的新坐标,然后在随后的 onDraws 中,检索位图并仅添加新坐标。要重置,只需再次设置背景位图(或像现在一样使用 View.setBackground)。我还没有对此进行测试,它可以使用一些增强功能,但希望它可以为您提供想法,并且如果如您所说,您一次只添加一个坐标,它会非常高效。

      public class CustomDraw extends View {
      
      public Bitmap backgroundBitmap;
      public Coordinate newCoordinate;
      
      ...   
      ...
      
      @Override
      public void onDraw(Canvas c) {
      
           // no super.onDraw as we are drawing everything
      
           Canvas backgroundCanvas = new Canvas(backgroundBitmap);
      
          ...
          ...
      
          // draw new co-ordinate to the background bitmap
          if (newCoordinate != null ){
               drawCoordinate(backgroundCanvas, newCoordinate);
               newCoordinate = null;
          }
      
          // draw the background bitmap to the view's canvas
          c.drawBitmap(backgroundBitmap, null, null);
      
          ...
          ...
      
      }
      

      【讨论】:

        猜你喜欢
        • 2023-03-27
        • 1970-01-01
        • 2019-09-17
        • 1970-01-01
        • 1970-01-01
        • 2013-01-30
        • 1970-01-01
        • 2013-06-21
        • 2011-07-13
        相关资源
        最近更新 更多