Search code examples
javaandroidmultithreadingarraylistconcurrentmodification

Getting ConcurrentModificationException from onLocationMethod


I am trying to update ArrayList of Locations as per below logic in a service, running in background thread through Runnable.I have edited code to show only relevant code. I am getting ConcurrentModificationException.

public static ArrayList<Location> locationPoints;


@Override
public void onLocationChanged(final Location location) {
    //Log.i(TAG, "onLocationChanged: " + location);
    Log.i(TAG, "onLocationChanged: " + locationPoints.size());

    ArrayList<Location> alnew= locationPoints;

    if(!locationPoints.isEmpty()){
        for(Location l:alnew){
            if(location.distanceTo(l)<=200.0f){
                locationPoints.add(l);
            }else{
                locationPoints.add(location);
            }
        }
    }else{
        locationPoints.add(location);
    }

    sendLocationsToActivity(locationPoints);
}

I want location objects going one after the other, but i see location objects increasing exponentially.

Result from Log in onLocationChanged is as below. Exception is emanating from ArrayList methods but I am unable to find a solution even after using all remedies given here.

onLocationChanged: 0
onLocationChanged: 1
onLocationChanged: 2
onLocationChanged: 4
onLocationChanged: 8
onLocationChanged: 16
onLocationChanged: 32

But if I delete all the ArrayList logic from onLocationChanged and simply add location objects to ArrayList, the results are the way I want

onLocationChanged: 0
onLocationChanged: 1
onLocationChanged: 2
onLocationChanged: 3
onLocationChanged: 4
onLocationChanged: 5

StackTrace:

FATAL EXCEPTION: main
Process: com.amreen.test, PID: 27053
Theme: themes:{default=overlay:com.resurrectionremix.pitchblack, fontPkg:com.resurrectionremix.pitchblack, com.android.systemui=overlay:com.resurrectionremix.pitchblack, com.android.systemui.headers=overlay:com.resurrectionremix.pitchblack, com.android.systemui.navbar=overlay:com.resurrectionremix.pitchblack}
java.util.ConcurrentModificationException
    at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)
    at com.amreen.test.MyLocationService.onLocationChanged(MyLocationService.java:146)
    at com.google.android.gms.location.internal.zzk$zzb.handleMessage(Unknown Source)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5458)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Solution

  • ConcurrentModificationException occurs when you modify the list (adding or removing elements) while traversing a list with Iterator. The for-each loop is nothing but syntactic sugar for java.util.Iterator. So here the logic is like:

    for() {
         if(someCondition) {
             locationPoints.add(sth);
       }
    }
    

    Rather than that you can try sth like:

    for() {
             if(someCondition) {
                 someOtherArrayList.add(sth);
           }
        }
    

    And once out of the loop and all then:

    locationPoints.addAll(someOtherArrayList);