【问题标题】:Resolving ConcurrentModificationException from modifying overlays通过修改覆盖解决 ConcurrentModificationException
【发布时间】:2012-12-17 03:01:37
【问题描述】:

我一直在尝试修复导致间歇性 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,但错误仍然出现。这可能是因为在前一个可运行对象终止之前将新的可运行对象推送到 UI 线程吗?我已经看到提到填充是比无效更好的方法,尽管我不完全确定它们有何不同。任何想法如何解决这个问题?

【问题讨论】:

    标签: java android debugging concurrency


    【解决方案1】:

    修改叠加层集应始终在 UI 线程上完成。 getOverlays()返回的ListMapView所有,它可以随时决定查看或操作列表。

    由于您正在处理大量地理点,很可能您的后台线程正在清除(或添加)覆盖,而 MapView 正在 UI 线程上对其进行迭代。这将触发ConcurrentModificationException,因为迭代器在其底层覆盖集更改时无效。有时,UI 线程无法立即看到更改,因此崩溃是间歇性的。

    设置叠加层通常是此类工作流程中较慢的部分。为避免并发修改,您可以在后台线程中设置叠加层,然后在 Runnable 内对 clear()add() 进行所有调用。 (另一种选择是使用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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 2015-03-08
      相关资源
      最近更新 更多