2012-05-30 2 views
0

У меня есть карта с пользовательским наложением и связкой маркеров. Поскольку я делаю группировку маркеров при изменении масштаба, мне нужно очистить оверлей, перегруппировать элементы для нового масштабирования и снова наложить на карту. Я делаю это в фоновом потоке, чтобы все получилось гладким. Таким образом, вы нажимаете для увеличения, маркеры исчезают, индикатор занятости отображается в углу, и на карте появляются новые маркеры. все будет гладко, так как это должно, однако, я получаю неоправданное изменение исключения, когда вы дважды увеличиваете масштаб в строке или увеличиваете масштаб и уменьшаете масштаб сразу. Я много читал об этом, но ни один вариант не подходит для меня. Например, перенос переноса карты на onPostExecute, который находится в пользовательском интерфейсе, предотвращает это, но замораживает карту для того, чтобы метки времени были нарисованы, и она теряет свою гладкость. Я попытался сделать список меток в подробном оверлейном синхронизированном списке, но не помог. Как я могу это предотвратить?Android maps itemizedoverlay ConcurrentModificationException

Это то, что я называю по изменению масштабирования:

private void drawItems() { 
    final MyMapView mw = this.mapView; 

    //remove existing first 
    //mw.getOverlays().remove(stuffOverlay); 
    stuffOverlay.clearAll(); 
    //mw.invalidate(); 

    new AsyncTask<String, Integer, String>() { 
    @Override 
    protected void onPreExecute() { 
     super.onPreExecute(); 
     ((ProgressBar)findViewById(R.id.mapProgressBar)).setVisibility(View.VISIBLE); 
    } 

    @Override 
    protected String doInBackground(String... params) { 
     //get items on map 
     HashMap<String, JSONArray> groupedItems = getItemsForZoom(mw.getZoomLevel()); 

     if (groupedItems==null) 
     return "done"; 

     //create a copy of it sometimes it was throwing concurentmodificationexception 
     HashMap<String, JSONArray> groupedItemsCopy = new HashMap<String, JSONArray> (groupedItems); 

     Iterator it = groupedItemsCopy.entrySet().iterator(); 
     while (it.hasNext()) { //loop over markers 
     try { 
      //get item 
      HashMap.Entry<String, Object> pair = (HashMap.Entry)it.next(); 
      JSONArray itemsInMarker = (JSONArray) pair.getValue(); 
      JSONObject itemData = (JSONObject) itemsInMarker.get(0); 

      //get truncated coordinates 
      String coordsKey = pair.getKey(); 
      String[] coordsSplitted = coordsKey.split("_"); 

      //add first marker to map 
      GeoPoint gp = new GeoPoint((int)(Double.parseDouble(coordsSplitted[0])*1E6), (int)(Double.parseDouble(coordsSplitted[1])*1E6)); 
      OverlayItem markerOverlay = new OverlayItem(gp, "marker", "snipper text"); 
      Drawable markerPic = ServerCall.drawableFromUrl(((JSONObject)((JSONObject)itemData.get("picture")).get("1")).get("picture_full")+"_0.png"); 
      //markerPic.setBounds(0, 0, markerPic.getIntrinsicWidth(), markerPic.getIntrinsicHeight()); 
      markerPic.setBounds(-25, -25, 50, 50); 
      markerOverlay.setMarker(markerPic); 
      stuffOverlay.addOverlay(markerOverlay, itemData); 

      if (stuffOverlay.size() > 0) { 
      mapView.getOverlays().add(stuffOverlay); 
      } 
     } catch (JSONException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     } 
     return "done"; 
    } 

    @Override 
    protected void onPostExecute(String result) { 
     super.onPostExecute(result); 
     ((ProgressBar)findViewById(R.id.mapProgressBar)).setVisibility(View.GONE); 
     mapView.invalidate(); 
    } 
    }.execute(); 
} 

Это мой детализированный оверлей:

private class StuffOverlay extends ItemizedOverlay { 
    private List<OverlayItem> mOverlays = Collections.synchronizedList(new ArrayList<OverlayItem>()); 
    private ArrayList<JSONObject> mStuff = new ArrayList<JSONObject>(); 
    public int currentItem; 
    Map mMap; 

    public StuffOverlay(Drawable defaultMarker, Map map) { 
    super(boundCenterBottom(defaultMarker)); 
    mMap = map; 
    populate(); //keep here 
    } 

    public void addOverlay(OverlayItem overlay, JSONObject stuffData) { 
    synchronized (mOverlays) { 
     mOverlays.add(overlay); 
    } 

    mStuff.add(stuffData); 
    setLastFocusedIndex(-1); //keep here 
    populate(); 
    } 

    public void clearAll() { 
    synchronized (mOverlays) { 
     mOverlays.clear(); 
    } 

    setLastFocusedIndex(-1); //keep here 
    populate(); 
    } 

    @Override 
    protected OverlayItem createItem(int i) { 
    synchronized (mOverlays) { 
     return mOverlays.get(i); 
    } 
    } 

    @Override 
    public int size() { 
    synchronized (mOverlays) { 
     return mOverlays.size(); 
    } 
    } 

    public void draw(Canvas canvas, MapView mapView, boolean shadow) { 
    if (!shadow) { 
     super.draw(canvas, mapView, false); 
    } 
    } 
} 

И это то, что я получаю, о (

05-30 20:45:35.485: W/dalvikvm(1139): threadid=3: thread exiting with uncaught exception (group=0x4001b188) 
05-30 20:45:35.485: E/AndroidRuntime(1139): Uncaught handler: thread main exiting due to uncaught exception 
05-30 20:45:35.495: E/AndroidRuntime(1139): java.util.ConcurrentModificationException 
05-30 20:45:35.495: E/AndroidRuntime(1139):  at java.util.AbstractList$SimpleListIterator.next(AbstractList.java:64) 
05-30 20:45:35.495: E/AndroidRuntime(1139):  at com.google.android.maps.OverlayBundle.draw(OverlayBundle.java:44) 
05-30 20:45:35.495: E/AndroidRuntime(1139):  at com.google.android.maps.MapView.onDraw(MapView.java:476) 
05-30 20:45:35.495: E/AndroidRuntime(1139):  at android.view.View.draw(View.java:6535) 
05-30 20:45:35.495: E/AndroidRuntime(1139):  at android.view.ViewGroup.drawChild(ViewGroup.java:1531) 
05-30 20:45:35.495: E/AndroidRuntime(1139):  at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258) 

ответ

1

Я думаю, что проблема может быть связана с этими линиями здесь:

 if (stuffOverlay.size() > 0) { 
     mapView.getOverlays().add(stuffOverlay); 
     } 

Вам нужно только добавить объект stuffOverlay в массив карты накладками один раз, и вы даже можете сделать это прежде, чем stuffOverlay имеет какие-либо предметы в нем. Я бы переместил mapView.getOverlays().add(stuffOverlay); в точку, где создается экземпляр stuffOverlay.

+0

отличное место, вы абсолютно правы, и это действительно разрешило мою проблему. Благодарю. – Stan

Смежные вопросы