Вопрос

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) OverlayItems. You can pretty much only add OverlayItems 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 ItemizedOverlays (with just one OverlayItem) in list of Overlays instead of OverlayItems 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);
    }
}

Другие советы

Got the same problem, and a workaround. It seems Google's code up (or down) the call chain gets terribly confused when you shrink the OverlayItem list in the onTap method. Apparently there's some index that isn't updated (or updated too early) - hence the IOOBE.

My solution is based on the fact that I also have a GestureDetector in my ItemizedOverlay subclass (I use the onSingleTapConfirmed() for adding items to my map).

  • in the ItemizedOverlay.onTap(int) function save the index of the OverlayItem just tapped, but don't modify the list (yet)
  • in onSingleTapConfirmed() check if the 'justTapped' variable is set.
    • If so, remove it from the list
    • call setLastFocusedIndex(-1) and populate() to update the Overlay internally
    • invalidate() the MapView to repaint.
  • (optionally) do a little happy dance to celebrate your working code.

Hope this helps anyone!

I had the same problem. In my case i had extended ItemizedOverlay, and inside - was keeping an array of OverlayItems. Each time I panned or zoomed the map, i was clearing the internal list of items, added new ones and then called populate. (By some example I found somewhere). The problem was that the base class - ItemizedOverlay, keeps an internal variable "lastFocusedIndex". After repopulating the list, if it is not reset - the next time you decide to click somewhere in the map - it first decided to remove the focus from the lastSelectedItem.... And now - if your new list contains less items than the value of the lastSelectedItem - then it fails with this exception.

The solution in my case was - after clearing the internal list of OverlayItems, to also invoke setLastFocusedIndex(-1) - this ensures that everything is reset.

Some notes on what was useful for me to debug it: 1. Decompiled ItemizedOverlay from the maps.jar from the android-sdk - Does not help, as this is only an API/Stub jar that does not contain the real classes used @ runtime 2. Using DDMS downloaded system/framwork/com.google.android.maps.jar 3. converted it using dex2jar, and then extracted the correct class file for decompilation

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top