I've been struggling with the following problem for some days now. I have found many threads regarding this topic, but all are a little different or there was no solution.
For my project I created a custom ItemizedOverlay
and added this to my MapView
. If I now remove the last item of the list of items I get an IndexOutOfBoundsException
claiming that the requested index is equal to the size of the ArrayList
. I.e. index 2 size 2 or index 0 size 0. From what other topics have told me I have already tried the populate()
and setLastFocusedIndex(-1)
methods. These have solved other problems I had, but not this one. When removing other items from the list it works fine, the problem only seems to occur for the last item.
I get the following Logcat output:
01-24 16:11:08.091: E/AndroidRuntime(916): Uncaught handler: thread main exiting due to uncaught exception
01-24 16:11:08.101: E/AndroidRuntime(916): java.lang.IndexOutOfBoundsException: Invalid location 0, size is 0
01-24 16:11:08.101: E/AndroidRuntime(916): at java.util.ArrayList.get(ArrayList.java:341)
01-24 16:11:08.101: E/AndroidRuntime(916): at com.google.android.maps.ItemizedOverlay.getItem(ItemizedOverlay.java:419)
01-24 16:11:08.101: E/AndroidRuntime(916): at com.google.android.maps.ItemizedOverlay.focus(ItemizedOverlay.java:538)
01-24 16:11:08.101: E/AndroidRuntime(916): at com.google.android.maps.ItemizedOverlay.onTap(ItemizedOverlay.java:455)
01-24 16:11:08.101: E/AndroidRuntime(916): at com.google.android.maps.OverlayBundle.onTap(OverlayBundle.java:83)
01-24 16:11:08.101: E/AndroidRuntime(916): at com.google.android.maps.MapView$1.onSingleTapUp(MapView.java:346)
01-24 16:11:08.101: E/AndroidRuntime(916): at android.view.GestureDetector.onTouchEvent(GestureDetector.java:506)
01-24 16:11:08.101: E/AndroidRuntime(916): at com.google.android.maps.MapView.onTouchEvent(MapView.java:628)
01-24 16:11:08.101: E/AndroidRuntime(916): at android.view.View.dispatchTouchEvent(View.java:3709)
01-24 16:11:08.101: E/AndroidRuntime(916): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:852)
01-24 16:11:08.101: E/AndroidRuntime(916): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
01-24 16:11:08.101: E/AndroidRuntime(916): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
01-24 16:11:08.101: E/AndroidRuntime(916): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
01-24 16:11:08.101: E/AndroidRuntime(916): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
01-24 16:11:08.101: E/AndroidRuntime(916): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1659)
01-24 16:11:08.101: E/AndroidRuntime(916): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1107)
01-24 16:11:08.101: E/AndroidRuntime(916): at android.app.Activity.dispatchTouchEvent(Activity.java:2061)
01-24 16:11:08.101: E/AndroidRuntime(916): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1643)
01-24 16:11:08.101: E/AndroidRuntime(916): at android.view.ViewRoot.handleMessage(ViewRoot.java:1691)
01-24 16:11:08.101: E/AndroidRuntime(916): at android.os.Handler.dispatchMessage(Handler.java:99)
01-24 16:11:08.101: E/AndroidRuntime(916): at android.os.Looper.loop(Looper.java:123)
01-24 16:11:08.101: E/AndroidRuntime(916): at android.app.ActivityThread.main(ActivityThread.java:4363)
01-24 16:11:08.101: E/AndroidRuntime(916): at java.lang.reflect.Method.invokeNative(Native Method)
01-24 16:11:08.101: E/AndroidRuntime(916): at java.lang.reflect.Method.invoke(Method.java:521)
01-24 16:11:08.101: E/AndroidRuntime(916): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
01-24 16:11:08.101: E/AndroidRuntime(916): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
01-24 16:11:08.101: E/AndroidRuntime(916): at dalvik.system.NativeStart.main(Native Method)
What bothers me about this is that it seems to be calling methods from the standard ItemizedOverlay
. I have not added a normal ItemizedOverlay
and I don't call super methods in my itemizedOverlay
except in the constructor. Still the error seems to occur in a normal ItemizedOverlay
, for which it would make sense that the ArrayList
is empty.
I hope someone can point me in the right direction since I really feel stuck here. Thanks in advance!
Here is my code:
public class GameItemOverlay extends ItemizedOverlay<Item> {
private ArrayList<Item> mOverlays = new ArrayList<Item>();
public GameItemOverlay(Drawable defaultMarker) {
super(boundCenterBottom(defaultMarker));
setLastFocusedIndex(-1);
populate();
}
public void itemDataReady(){
mOverlays = GameSession.items;
setLastFocusedIndex(-1);
populate();
}
@Override
protected Item createItem(int i) {
return mOverlays.get(i);
}
@Override
public int size() {
return mOverlays.size();
}
@Override
protected boolean onTap(int i){
GameSession.remove(mOverlays.get(i).getID()); //Removes the item according to it's position
setLastFocusedIndex(-1);
populate();
return true;
}
}
It took me a while to figure the problem. I think the answer to this question is that ItemizedOverlay
is not intended to be used to manage (add and remove) OverlayItem
s. You can pretty much only add OverlayItem
s to ItemizedOverlay
and if you want to change any item, you need to recreate ItemizedOverlay
(not efficient). To solve this problem you need to manage ItemizedOverlay
s (with just one OverlayItem
) in list of Overlay
s instead of OverlayItem
s in ItemizedOverlay
. Something like that:
public class SomeActivity extends MapActivity {
private SomeMapView mView;
// Rest of the code ...
private void sendRequest(GeoPoint point)
{
List<Overlay> mOverlays = mView.getOverlays();
// Show red marker
OverlayItem item = new OverlayItem(point, "Hello", "world");
MarkerItemizedOverlay itemOverlay = new MarkerItemizedOverlay(drawable, mView);
itemOverlay.addOverlay(item);
mOverlays.add(itemOverlay);
}
}
public class MarkerItemizedOverlay extends ItemizedOverlay<OverlayItem> {
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
MapView mView;
// Rest of the code ...
@Override
protected boolean onTap(int index) {
List<Overlay> mOverlays = mView.getOverlays();
mOverlays.remove(this);
}
}