The ArrayIndexOutOfBounds exception is usually encountered because you've done one or more of the following:
- Overlayitem getItem(int position) returns null in your ItemizedOverlay
- The set of items is empty (related to above).
- You're concurrently modifying your backing Collection of OverlayItems while the draw() method is iterating through them.
I've read some crazy ideas about how to solve the 2nd problem, your backing collection is empty, and ItemizedOverlay pukes. This is very easy to workaround. Override the draw() methods, and return early. Here's an example:
public boolean draw(Canvas canvas, MapView mapView, boolean shadow,long when) {
if (myBackingList.isEmpty()) {
return false; // False means there's no need to immediately redraw.
}
}
Finally, it's important to know that when ItemizedOverlay is executing the draw() methods, it's actually looping through your Collection of OverlayItems by calling getItem() and size(). During this time it would be unwise to modify the collection. Your first instinct is probably to use a synchronized collection or call Collections.synchronizedList (or whichever is appropriate). But this probably won't help because ItemizedOverlay isn't calling the iterator on your collection, it doesn't know what your collection is. Instead, it's calling getItem(), N times.
The approach that works is to synchronize access to your collection in getItem(), size(), and and your call to super.draw(). Additionally, you'll need to synchronize wherever in your code you modify the collection.
So to wrap up, make sure you override draw() to handle the empty set scenario and synchronize access to your backing collection.
Good luck!
Thanks for the post. It's very helpful. I'm not exactly sure how to implement "synchronize access to your backing collection". I'm new to Java, but I appreciate you pointing me in the right direction.
ReplyDeleteMatt, I believe that "synchronize access to your backing collection" means placing a "synchronized("your_overlay_list"){
ReplyDelete} block around the code inside of any methods that access or modify your list of overlays.
For example:
@Override
public void addOverlay(OverlayItem overlay){
synchronized (mOverlays){
mOverlays.add(overlay);
setLastFocusedIndex(-1);
populate();
}
}