刷新地图itemizeoverlay给出ArrayIndexOutOfBoundsException



使用com.google.android.maps API,我有一个MapActivity,它使用ItemizedOverlayMapView上放置几个(最多约1000个)图标。当LocationListener检测到设备移动了一定距离(目前为5米,但这只是为了测试)时,我想刷新(或者只是添加到列表中)图标。

我已经添加了setLastFocusedIndex(-1)populate(),但我的itemizeoverlay仍然崩溃。

我认为当我向列表中添加更多项目时它会崩溃,但有时即使我不移动手机它也会崩溃。第一次更新时崩溃。我不能从LogCat中确切地知道是什么触发了错误。

我的MapActivity是基于各种教程:

EDIT:调整代码来批量更新项目,但它仍然崩溃

public class NearbyActivity extends MapActivity implements VenueCatalogListener {
    private final String TAG = this.getClass().getSimpleName();
    List<Overlay> mapOverlays;
    HelloItemizedOverlay itemizedOverlay;
    private MapController mapController;
    private MapView mapView;
    private LocationManager locationManager;
    private int latE6;
    private int lonE6;
    private Location current_location;
    private VenuesFromServer venues_from_server;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        venues_from_server = new VenuesFromServer(this);
        setupViews();
    }
    private void setupViews() {
        setContentView(R.layout.nearby_view);

        RelativeLayout linearLayout = (RelativeLayout) findViewById(R.id.mapMainLayout);
        mapView = new MapView(this, PreferencesManager.CLUBBERIA_MAPS_API_KEY);
        initializeMap();
        linearLayout.addView(mapView);
    }
    private void initializeMap() {
        mapView.setKeepScreenOn(true);
        mapView.setClickable(true);
        mapView.setBuiltInZoomControls(true);
        mapController = mapView.getController();
        mapController.setZoom(mapView.getMaxZoomLevel()-5); // Zoom 1 is world view
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, new GeoUpdateHandler());
        mapOverlays = mapView.getOverlays();
        if(itemizedOverlay == null) {
            Drawable drawable = this.getResources().getDrawable(R.drawable.icon);
            itemizedOverlay = new HelloItemizedOverlay(drawable);
            mapOverlays.add(itemizedOverlay);
        }
    }
    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }
    public class GeoUpdateHandler implements LocationListener {
        @Override
        public void onLocationChanged(Location location) {
            if(current_location == null) {
                current_location = location;
            }
            int lat = (int) (location.getLatitude() * 1E6);
            int lng = (int) (location.getLongitude() * 1E6);
            GeoPoint point = new GeoPoint(lat, lng);
            if(current_location.distanceTo(location) > 5) {
                // this kicks off an async task that will call back to venueListUpdated() below
                venues_from_server.getVenueJSONFromServer(location.getLatitude(), location.getLongitude(), 19);
            }
            mapController.animateTo(point); //  mapController.setCenter(point);
        }
        @Override
        public void onProviderDisabled(String provider) {
        }
        @Override
        public void onProviderEnabled(String provider) {
        }
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
        }
    }
    @Override
    public void venueListUpdated() {
        // Base.B.arrayVenuesMap is an ArrayList<Venue>
        for(int i=0;i<Base.B.arrayVenuesMap.size();i++) {
            Venue _venue = Base.B.arrayVenuesMap.get(i);
            latE6 =  (int) (_venue.latitude*1e6);
            lonE6 = (int) (_venue.longitude*1e6);
            GeoPoint point = new GeoPoint(latE6, lonE6);
            OverlayItem overlayitem = new OverlayItem(point, _venue.name, "");
            Drawable drawable = this.getResources().getDrawable(R.drawable.icon);
            itemizedOverlay.addOverlay(overlayitem, drawable);
        }
        itemizedOverlay.batchPopulate();
    }
}

我的itemizeoverlay看起来像这样:

public class HelloItemizedOverlay extends ItemizedOverlay<OverlayItem> {
    private ArrayList<OverlayItem> mOverlays = null;
    public HelloItemizedOverlay(Drawable defaultMarker) {
        super(boundCenterBottom(defaultMarker));
        mOverlays = new ArrayList<OverlayItem>();
        setLastFocusedIndex(-1);
        populate();
    }
    public void addOverlay(OverlayItem overlay, Drawable defaultMarker) {
        if(!mOverlays.contains(overlay)) {
            setLastFocusedIndex(-1);
            overlay.setMarker(boundCenterBottom(defaultMarker));
            mOverlays.add(overlay);
        }
    }
    public void batchPopulate() {
        setLastFocusedIndex(-1);
        populate();
    }
    @Override
    protected OverlayItem createItem(int i) {
        return mOverlays.get(i);
    }
    @Override
    public int size() {
        return mOverlays.size();
    }
}

Logcat的功能如下:

11-24 18:28:02.245: D/AsyncJSONClient(18382): starting connect with this many pairs: 0; thread 17
11-24 18:28:02.255: E/AndroidRuntime(18382): FATAL EXCEPTION: main
11-24 18:28:02.255: E/AndroidRuntime(18382): java.lang.ArrayIndexOutOfBoundsException
11-24 18:28:02.255: E/AndroidRuntime(18382):    at com.google.android.maps.ItemizedOverlay.getIndexToDraw(ItemizedOverlay.java:211)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at com.google.android.maps.ItemizedOverlay.draw(ItemizedOverlay.java:240)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at com.google.android.maps.Overlay.draw(Overlay.java:179)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at com.google.android.maps.OverlayBundle.draw(OverlayBundle.java:42)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at com.google.android.maps.MapView.onDraw(MapView.java:530)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.View.draw(View.java:6918)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.View.draw(View.java:6921)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.widget.FrameLayout.draw(FrameLayout.java:357)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.View.draw(View.java:6921)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.widget.FrameLayout.draw(FrameLayout.java:357)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.View.draw(View.java:6921)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.widget.FrameLayout.draw(FrameLayout.java:357)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1947)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewRoot.draw(ViewRoot.java:1539)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewRoot.performTraversals(ViewRoot.java:1275)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.view.ViewRoot.handleMessage(ViewRoot.java:1876)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.os.Handler.dispatchMessage(Handler.java:99)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.os.Looper.loop(Looper.java:123)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at android.app.ActivityThread.main(ActivityThread.java:3728)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at java.lang.reflect.Method.invokeNative(Native Method)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at java.lang.reflect.Method.invoke(Method.java:507)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:864)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622)
11-24 18:28:02.255: E/AndroidRuntime(18382):    at dalvik.system.NativeStart.main(Native Method)
11-24 18:28:02.255: W/ActivityManager(308):   Force finishing activity com.clubberia.android/.ClubberiaMain

我怎么能偶尔添加项目itemizeoverlay没有崩溃?

我知道这有点老了,但是@cgwylie几乎是对的。

你应该在更新覆盖值后调用populate()…然后你可以调用postInvalidate()

当你在ItemizedOverlay中更改项目时,你需要在MapView上调用postInvalidate()来让它知道你已经调整了覆盖,这样它就不会再尝试绘制不在列表中的项目了。

在您的venueListUpdated()中,您可以尝试在调用itemizedOverlay.addOverlay(overlayitem, drawable)后添加mapView.postInvalidate()来解决您的问题。

最新更新