高效绘制ArrayList的onDraw方法

5
我有一个自定义视图,我在上面绘制一个坐标点的ArrayList(这是一个自定义类,只包含x和y位置)。随着越来越多的坐标点被添加到ArrayList中,绘图明显变慢。我想知道是否有更有效的方法来绘制这个ArrayList,或者是否可以只添加一个新的坐标点(因为在调用invalidate之间,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);
    }
}
}

感谢您的帮助!
3个回答

3
你每次循环时都在声明 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方法,我相信您已经知道。或者,如果您的Coordinate仅保存x和y位置,则可以使用java Point类。


谢谢您的建议。我一定会去了解一下。 - Jon Rubins

1
我的方法是在每个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);

    ...
    ...

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接