2011-11-24 6 views
6

Utilizzando l'API com.google.android.maps, ho un MapActivity che utilizza ItemizedOverlay posizionare diversi (fino a circa il 1000) le icone su un MapView. Voglio aggiornare (o forse aggiungere all'elenco) le icone quando lo LocationListener rileva che il dispositivo ha spostato una certa distanza (attualmente 5 metri, ma è solo per il test).mappa rinfrescante ItemizedOverlay dà ArrayIndexOutOfBoundsException

Ho aggiunto setLastFocusedIndex(-1) e populate(), ma il mio ItemizedOverlay si blocca ancora. Penso che stia andando in crash quando aggiungo altri elementi alla lista, ma a volte sembra andare in crash anche se non muovo il mio telefono. Arresta in modo anomalo al primo aggiornamento. Non posso dire da LogCat esattamente cosa sta causando l'errore.

mio MapActivity è basato fuori vari tutorial:

EDIT: ottimizzato il codice per fare un batch update of items ma si blocca ancora

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(); 
    } 
} 

mio ItemizedOverlay assomiglia a questo:

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 presenta le seguenti linee:

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 

Come posso aggiungere occasionalmente elementi a ItemizedOverlay senza arresti anomali?

risposta

3

ni conoscono la sua un po 'vecchio, ma @cgwylie è quasi giusto ..

si dovrebbe chiamare populate() dopo l'aggiornamento dei valori sovrapposizioni ... e poi è possibile chiamare il hmm postInvalidate()

0

Quando si modificano gli elementi in un ItemizedOverlay, è necessario chiamare postInvalidate() sul MapView di farle sapere che hai regolato le sovrapposizioni in modo da non cercare di attirare gli elementi che non sono nella lista di nuovo.

Nel tuo venueListUpdated() puoi provare ad aggiungere mapView.postInvalidate() dopo aver chiamato itemizedOverlay.addOverlay(overlayitem, drawable) per risolvere il tuo problema.

+0

. Ho appena provato il tuo suggerimento, ma non ha funzionato. Grazie comunque! –

+0

Fantastico, scusa, non ha funzionato, per me ha risolto il problema in passato. – cgwyllie