我一直在尝试修复导致间歇性ConcurrentModificationException的错误。发生了什么事情,我有大量的地理输出与ItemizedOverlay一起显示。但是,移动地图时,我正在尝试清除所有当前的叠加项(地理位置),并用适合新视图窗口的新点替换它们。
因此我有一个回调函数可以清除旧的叠加层并用新叠加层替换它们。我认为我的错误源于多个线程试图同时执行此操作。相关部分如下。我对叠加和这样的工作如何处于低水平的理解非常有限,所以我想知道是否有人可以证实(或反驳)这可能导致问题。
//first clear out the old overlays
List<Overlay> mapOverlays = mapView.getOverlays();
mapOverlays.clear();
//create the new overlays, each initialized with appropriate Drawables
MenuOverlay lowOverlay = new MenuOverlay(this, lowRisk);//(all valid Drawables)
MenuOverlay medOverlay = new MenuOverlay(this, medRisk);
MenuOverlay highOverlay = new MenuOverlay(this, highRisk);
//populate the overlays
//add the new overlays into the list of overlays
mapOverlays.add(lowOverlay);
mapOverlays.add(medOverlay);
mapOverlays.add(highOverlay);
//make the map refresh; this operation has to be pushed to another thread
Runnable runnable = new Runnable() {
public void run() {
mapView.invalidate();
}
};
runOnUiThread(runnable);
我尝试制作此方法synchronized
,但错误仍然存在。这可能是因为新的runnable在上一次runnable终止之前被推送到UI线程吗?我已经看到提到填充是一种比无效更好的方式,虽然我不完全确定它们是如何不同的。有任何想法如何解决这个问题?
答案 0 :(得分:1)
应始终在UI线程上修改叠加集。 List
返回的getOverlays()
归MapView
所有,并且可以随时决定查看或操作列表。
由于您正在使用大量的地理位置,因此当MapView
在UI线程上迭代它们时,您的后台线程可能正在清除(或添加)叠加层。这将触发ConcurrentModificationException
,因为迭代器在其基础覆盖集更改时无效。有时,UI线程不会立即看到更改,因此崩溃是间歇性的。
设置叠加层通常是此类工作流程的缓慢部分。为避免同时修改,您可以在后台线程中设置叠加层,然后在clear()
内拨打add()
和Runnable
的所有电话。 (另一种选择是使用AsyncTask
。)
例如:
// Slow setup steps
final MenuOverlay lowOverlay = new MenuOverlay(this, lowRisk);
final MenuOverlay medOverlay = new MenuOverlay(this, medRisk);
final MenuOverlay highOverlay = new MenuOverlay(this, highRisk);
Runnable runnable = new Runnable() {
public void run() {
// Anything that touches UI widgets (map, overlay set, views, etc.)
List<Overlay> mapOverlays = mapView.getOverlays();
mapOverlays.clear();
mapOverlays.add(lowOverlay);
mapOverlays.add(medOverlay);
mapOverlays.add(highOverlay);
mapView.invalidate();
}
};
runOnUiThread(runnable);