2

我试图根据以下逻辑在服务中更新ArrayList的位置,通过Runnable.I在后台线程中运行我编辑的代码仅显示相关代码。我得到ConcurrentModificationException从onLocationMethod获取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

但是,如果我删除所有来自onLocationChangedArrayList逻辑并简单地添加位置obj学分到ArrayList,结果的方式我想

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) 
+0

请提供(短)异常的堆栈跟踪,并请尽量减少你的代码,并提供一个[*最小*,完整,可验证的示例](HTTP ://stackoverflow.com/help/mcve)。您是否搜索其他ConcurrentModificationException问题?这个话题有很多资源。 –

+0

我按照说明进行了更改。 – user7090887

+1

当您使用Iterator遍历列表时修改列表(添加或删除元素)时,会发生ConcurrentModificationException。这里for-each循环内部使用迭代器。您需要使用另一个数组列表并保留元素,并在退出循环后更新原始集合。 –

回答

2

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

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

,而不是你可以尝试某事象:

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

而且一旦出了循环和所有然后:

locationPoints.addAll(someOtherArrayList); 
+0

我已经更新了代码,但问题仍然存在,请检查我是否新建了arrayList。但是在写这篇评论的时候,我意识到我犯了一个提到同一个对象的错误。我会按照你的指示去尝试。 – user7090887

+0

你的方法解决了异常,但奇怪的结果仍然继续 – user7090887

1

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

这个类的迭代器和listIterator方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时候,结构性地修改列表,除了通过迭代器自己的remove或add方法以外,迭代器都会抛出一个ConcurrentModificationException的。因此,面对并发修改,迭代器快速而干净地失败,而不是在将来某个未确定的时间冒着任意的,非确定性的行为风险。

您下注首先得到迭代器,然后将其用于添加。 例

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