1

I've tried to look this up in other threads and apply the solutions I've found there, to my own issue, but nothing seems to have worked. So here goes:

In one class I have, which creates a new Polygon Overlay:

 public void addPolyLines(ArrayList<KrollDict> polyLines){
    // Remove the line overlay
    List<Overlay> mMapOverlays = view.getOverlays();
    boolean rm = mMapOverlays.remove(polyLineOverlay);    

    polyLineOverlay = new PolygonOverlay(polyLines); // KEY LINE

    mMapOverlays.add(polyLineOverlay);
    view.invalidate();
}

And these are the guts of my PolygonOverlay class. A concurrent modification exception is thrown at the while(it.hasNext()) line and I can't figure out why. I don't believe I'm modifying the mPolyLines array. drawLines is called from the Overlays native draw method, and sometimes it looks like it's called constantly.

ArrayList<KrollDict> mPolyLines;

public PolygonOverlay(ArrayList<KrollDict> polyLines){
        mPolyLines = polyLines;
}

public void drawLines(MapView mv, Canvas canvas) {
        Iterator<KrollDict> it = mPolyLines.iterator();

        // Go through each line
        while(it.hasNext()){// CONCURRENTMODIFICATIONEXCEPTION THROWN HERE
            KrollDict kd = it.next();
            String[] pointsArr = kd.getStringArray("points");
            String color = kd.getString("color");
            float width = new Float(kd.getDouble("width")).floatValue(); 
            int alpha = kd.getInt("alpha");

            int x1 = -1, y1 = -1, x2 = -1, y2 = -1;
            Paint paint = new Paint();
            paint.setColor(Color.parseColor(color));
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(width);
            //paint.setAlpha(alpha);

            // Loop through the coordinates
            for(int i = 0; i< pointsArr.length; i++){
                String[] coordinates = convertStringToArray(pointsArr[i]);
                Double latitude = new Double(Double.parseDouble(coordinates[3]) * 1E6);
                Double longitude = new Double(Double.parseDouble(coordinates[1]) * 1E6);
                GeoPoint gp = new GeoPoint(latitude.intValue(), longitude.intValue());                                      

                Point point = new Point();
                point = mv.getProjection().toPixels(gp, point);                 

                x2 = point.x;
                y2 = point.y;
                if (i > 0) {                        
                    canvas.drawLine(x1, y1, x2, y2, paint);
                }
                x1 = x2;
                y1 = y2;
            }
        }// while
    }
Leonidas
  • 2,110
  • 4
  • 20
  • 31
  • see this thread http://stackoverflow.com/questions/1775717/explain-synchronization-of-collections-when-iterators-are-used – aviad Jan 23 '12 at 15:31
  • I see nothing wrong with the code you've posted. Guessing wildly, but perhaps you are thinking that the overlay is iterating it's own private copy of your ArrayList, and that you're updating a separate one elsewhere (maybe on another thread), whereas they are in fact the same object. Is that possible? – Reuben Scratton Jan 23 '12 at 15:38
  • That's entirely possible. The only other place I add / remove from that ArrayList is in another class, which is in another thread, but it only happens when the user press an add / remove button, after which all this code gets called. Do you think that could be it? I assumed that they were called one after another... – Leonidas Jan 23 '12 at 16:06

1 Answers1

1

Try

public PolygonOverlay(ArrayList<KrollDict> polyLines){  
    mPolyLines = (ArrayList<KrollDict>)polyLines.clone();  
}   

By making a clone, you should be safe against someone changing the list while you are iterating over it.

Marc Van Daele
  • 2,856
  • 1
  • 26
  • 52
  • 1
    Or use the copy constructor: `mPolyLines = new ArrayList(polyLines)`, saves the cast. – Matt Jan 23 '12 at 15:34