MapView ConcurrentModificationException

时间:2010-06-28 13:58:05

标签: android exception concurrency android-mapview

正如标题所示,我试图在两个地点之间创建路线时(有时)会发生并发修改... 这是我的代码(如果您想知道MyOverlay没有尝试访问地图中的其他叠加层)

    private class fillRouteTask extends AsyncTask<Void, GeoPoint, Void> {

  /**
   * create the url to call to get the route
   * 
   * @param src
   * @param dest
   * @return
   */
  private StringBuilder createUrl(GeoPoint src, GeoPoint dest) {
   // connect to map web service
   StringBuilder urlString = new StringBuilder();
   urlString.append("http://maps.google.com/maps?f=d&hl=en");
   urlString.append("&saddr=");// from
   urlString.append(Double
     .toString((double) src.getLatitudeE6() / 1.0E6));
   urlString.append(",");
   urlString.append(Double
     .toString((double) src.getLongitudeE6() / 1.0E6));
   urlString.append("&daddr=");// to
   urlString.append(Double
     .toString((double) dest.getLatitudeE6() / 1.0E6));
   urlString.append(",");
   urlString.append(Double
     .toString((double) dest.getLongitudeE6() / 1.0E6));
   urlString.append("&ie=UTF8&0&om=0&output=kml");
   Log.d("xxx", "URL=" + urlString.toString());

   return urlString;
  }

  /**
   * create the connection to google url
   * 
   * @param src
   * @param dest
   * @return
   */
  private String connectToUrl(GeoPoint src, GeoPoint dest) {

   // get the kml (XML) doc. And parse it to get the
   // coordinates(direction
   // route).
   Document doc = null;
   HttpURLConnection urlConnection = null;
   URL url = null;
   try {
    url = new URL(createUrl(src, dest).toString());
    urlConnection = (HttpURLConnection) url.openConnection();
    urlConnection.setRequestMethod("GET");
    urlConnection.setDoOutput(true);
    urlConnection.setDoInput(true);
    urlConnection.connect();

    DocumentBuilderFactory dbf = DocumentBuilderFactory
      .newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();
    doc = db.parse(urlConnection.getInputStream());

    if (doc.getElementsByTagName("GeometryCollection") != null
      && doc.getElementsByTagName("GeometryCollection")
        .getLength() > 0) {
     return doc.getElementsByTagName("GeometryCollection").item(
       0).getFirstChild().getFirstChild().getFirstChild()
       .getNodeValue();
    }

   } catch (MalformedURLException e) {
    Log.d("test", e.getLocalizedMessage());
   } catch (IOException e) {
    Log.d("test", e.getLocalizedMessage());
   } catch (ParserConfigurationException e) {
    Log.d("test", e.getLocalizedMessage());
   } catch (SAXException e) {
    Log.d("test", e.getLocalizedMessage());
   }
   return null;
  }

  protected Void doInBackground(Void... arg0) {
   try {
    // get the current overlays present in the map
    List<Overlay> overs = Collections.synchronizedList(mapView
      .getOverlays());
    String path = connectToUrl(orig, dest);
    if (path != null) {
     Log.d("xxx", "path=" + path);
     String[] pairs = path.split(" ");
     String[] lngLat = pairs[0].split(",");

     GeoPoint startGP = new GeoPoint((int) (Double
       .parseDouble(lngLat[1]) * 1E6), (int) (Double
       .parseDouble(lngLat[0]) * 1E6));

     overs.add(new MyOverlay(startGP, startGP, 1));
     GeoPoint gp1;
     GeoPoint gp2 = startGP;
     for (int i = 1; i < pairs.length; i++) // the last one would
     // be
     // crash
     {
      lngLat = pairs[i].split(",");
      gp1 = gp2;
      // watch out! For GeoPoint, first:latitude,
      // second:longitude
      gp2 = new GeoPoint(
        (int) (Double.parseDouble(lngLat[1]) * 1E6),
        (int) (Double.parseDouble(lngLat[0]) * 1E6));
      Log.d("xxx", "pair:" + pairs[i]);
      publishProgress(gp1, gp2);
     }
     overs.add(new MyOverlay(dest, dest, 3)); // use
     // the
     // default
     // color
     drawn = false;
    } else {
     m_handler.post(new Runnable() {

      public void run() {
       Toast.makeText(getApplicationContext(),
         "Problem in getting the directions",
         Toast.LENGTH_SHORT).show();
      }
     });
    }
   } catch (Exception e) {
    m_handler.post(new Runnable() {

     public void run() {
      Toast.makeText(getApplicationContext(),
        R.string.errorrouteLoad, Toast.LENGTH_LONG)
        .show();
     }
    });
   }
   return null;

  }

  /*
   * (non-Javadoc)
   * 
   * @see android.os.AsyncTask#onProgressUpdate(Progress[])
   */
  @Override
  protected void onProgressUpdate(GeoPoint... values) {
   // TODO Auto-generated method stub
   List<Overlay> overs = Collections.synchronizedList(mapView
     .getOverlays());
   overs.add(new MyOverlay(values[0], values[1], 2, 0x0000ff));

  }

  /*
   * (non-Javadoc)
   * 
   * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
   */
  @Override
  protected void onPostExecute(Void result) {
   // TODO Auto-generated method stub
   Log.d("routing", "done");
   mapView.postInvalidate();
  }
 }

1 个答案:

答案 0 :(得分:4)

您只能修改UI线程上的叠加层。您需要在AsyncTask的onPostExecute方法中将新数据添加到overlay中。