2011-03-12 88 views
1

嗨,我可以使用一些幫助修復併發修改異常我收到了,我認爲這是使用列表和使用線程,這意味着我試圖訪問它在同一時間導致它鎖定,但我不知道如何解決它,有什麼幫助?併發修改異常如何修復它?

編輯這隻發生在連續兩次運行下面的代碼後,它只能正常工作一次。

全球: 列表mapOverlays; PointOverlay pointOverlay;

在的onCreate:

//Get the current overlays of the mapView and store them in the list 
mapOverlays = mapView.getOverlays(); 
//Get the image to be used as a marker 
drawable = this.getResources().getDrawable(R.drawable.guy); 
//Create the drawable and bind its centre to the bottom centre 
pointOverlay = new PointOverlay(drawable, this); 

在getLocs:

//Used to grab location near to the phones current location and then draw 
//the location within range to the map 
public void getNearLocs(View v) 
{ 
    new Thread()//create new thread 
    { 
    public void run()//start thread 
    { 
     //Grab new location 
     loc = locManager.getLastKnownLocation(locManager.getBestProvider(locCriteria, true)); 

     //Get the lat and long 
     double lat = loc.getLatitude(); 
     double lon = loc.getLongitude(); 

     //Convert these to string to prepare for sending to server 
     String sLat = Double.toString(lat); 
     String sLon = Double.toString(lon); 

     //Add them to a name value pair 
     latLonPair.add(new BasicNameValuePair("lat", sLat)); 
     latLonPair.add(new BasicNameValuePair("lon", sLon)); 
     Log.i("getNearLocs", "Lon: " + sLon + " Lat: " + sLat);//debug 

     //http post 
     try 
     { 
      //Create a new httpClient 
      HttpClient httpclient = new DefaultHttpClient(); 
      //Create a post URL 
      HttpPost httppost = new HttpPost("http://www.nhunston.com/ProjectHeat/getLocs.php"); 
      //set the Entity of the post (information to be sent) as a new encoded URL of which the info is the nameValuePairs   
      httppost.setEntity(new UrlEncodedFormEntity(latLonPair)); 
      //Execute the post using the post created earlier and assign this to a response 
      HttpResponse response = httpclient.execute(httppost);//send data 

      //Get the response from the PHP (server) 
      InputStream in = response.getEntity().getContent(); 

      //Read in the data and store it in a JSONArray 
      JSONArray jPointsArray = new JSONArray(convertStreamToString(in)); 

      Log.i("From Server:", jPointsArray.toString()); //log the result 

      //Clear the mapView ready for redrawing 
      mapView.postInvalidate(); 

      //Loop through the JSONArray 
      for(int i = 0; i < jPointsArray.length(); i++) 
      { 
       //Get the object stored at the JSONArray position i 
       JSONObject jPointsObj = jPointsArray.getJSONObject(i); 

       //Extract the values out of the objects by using their names 
       //Cast to int 
       //Then* 1e6 to convert to micro-degrees 
       GeoPoint point = new GeoPoint((int)(jPointsObj.getDouble("lat") *1e6), 
               (int)(jPointsObj.getDouble("lon") *1e6)); 
       //Log for debugging 
       Log.i("From Server:", String.valueOf((int) (jPointsObj.getDouble("lat") * 1e6))); //log the result 
       Log.i("From Server:", String.valueOf((int) (jPointsObj.getDouble("lon") * 1e6))); //log the result 

       //Create a new overlayItem at the above geoPosition (text optional) 
       OverlayItem overlayitem = new OverlayItem(point, "Test", "Test"); 

       //Add the item to the overlay 
       pointOverlay.addOverlay(overlayitem); 
       //Add the overlay to the mapView 
       mapOverlays.add(pointOverlay); 
       //mapView.refreshDrawableState(); 
      } 
     } 
     catch(Exception e) 
     { 
      Log.e("getNearLocs", e.toString()); 
     } 
    } 
}.start();//start thread 
} 
+2

這將有助於查看堆棧跟蹤。哦,並且由於沒有行號,所以您發佈的代碼中的哪一行會在堆棧跟蹤中指明。 – Speck 2011-03-12 03:17:50

回答

4

問題是,當一些其他線程正在讀取列表時,您正在修改覆蓋項目列表。

我懷疑這個問題與您做後臺任務的方式有關。您只能修改UI(主線程)上的UI。您不應該將重疊項添加到線程中的地圖。查看AsyncTask以查看如何正確執行後臺任務並更新UI。這也有助於閱讀Android dev站點上Threading的文章。

4

問題是可能您的來電mapOverlays.add()。這可能是在另一個線程或代碼片段迭代列表的同時發生的。當一個線程遍歷一個集合(通常使用迭代器)並且另一個線程嘗試從結構上更改集合時,會引發併發修改異常。

我會建議尋找mapOverlays可以從兩個不同的線程同時訪問的地方,並在列表上同步。

+0

不知道反對票是什麼意思? – 2011-03-12 04:27:26