简体   繁体   中英

Concurrent Modification Exception How to Fix It?

Hi I could use some help fixing the Concurrent Modification Exception I'm getting, I think it is something to do with the use of the List and the use of a thread which means I'm attempting to access it at the same time causing it to lock, but I dont know how to fix it, any help?

edit This only occurs after I run the code below twice in a row it works fine only once.

Global: List mapOverlays; PointOverlay pointOverlay;

In 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);

In 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
}

The problem is likely your call to mapOverlays.add(). This is probably happening at the same time another thread or piece of code is iterating over list. Concurrent modification exceptions are thrown when one thread is iterating over a collection (typically using an iterator) and another thread tries to structurally change the collection.

I would suggest looking for places where mapOverlays may be accessed simultaneously from two different threads and synchrnoizing on the list.

The problem is that you are modifying the list of overlay items while some other thread is reading the list.

I suspect the problem has to do with the way you are doing your background tasks. You can only modify the UI on the UI (main thread). You shouldn't be adding the overlay items to the Map in the Thread. Check out AsyncTask to see how to properly do background tasks and also update the UI. It would also help to read the article on Threading on the Android dev site.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM