从 onLocationMethod 获取 ConcurrentModificationException

Getting ConcurrentModificationException from onLocationMethod

我正在尝试根据服务中的以下逻辑更新 ArrayList 个位置,运行 在后台线程中通过 Runnable.I 编辑了代码以仅显示相关代码。我得到 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);
}

我希望位置对象一个接一个地移动,但我看到位置对象呈指数增长。

登录onLocationChanged的结果如下。异常来自 ArrayList 方法,但即使使用了此处给出的所有补救措施,我也无法找到解决方案。

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

但如果我从 onLocationChanged 中删除所有 ArrayList 逻辑并简单地将位置对象添加到 ArrayList,结果就是我想要的方式

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

堆栈跟踪:

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)

ConcurrentModificationException 在使用 Iterator 遍历列表时修改列表(添加或删除元素)时发生。 for-each 循环只不过是 java.util.Iterator 的语法糖。所以这里的逻辑是这样的:

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

除此之外,您还可以尝试以下操作:

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

一旦跳出循环,然后:

locationPoints.addAll(someOtherArrayList);

是因为ArrayList的实现,请参考文档 ArrayList document

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

你打赌首先得到迭代器,然后用它来添加。 示例

Iterator<Location> iter = locationPoints.iterator(); while (iter.hasNext()) { Location location = iter.next(); if(location.distanceTo(l)<=200.0f){ iter.add(l); }else{ iter.add(location); } }