简体   繁体   English

通过修改叠加层来解决ConcurrentModificationException

[英]Resolving ConcurrentModificationException from modifying overlays

I've been trying to fix an error causing an intermittent ConcurrentModificationException. 我一直在尝试解决导致间歇性ConcurrentModificationException的错误。 What's happening is that I have tons of geopoints being displayed with an ItemizedOverlay. 发生的事情是,我有大量的Geopoints用ItemizedOverlay显示。 When the map is moved, however, I'm trying to clear out all current overlay items (the geopoints) and replace them with new points appropriate to the new view window. 但是,在移动地图时,我试图清除所有当前的重叠项目(地理点),并用适合于新视图窗口的新点替换它们。

I therefore have a callback function that clears out the old overlays and replaces them with new ones. 因此,我有一个回调函数,用于清除旧的叠加层并用新的叠加层替换。 I think my bug stems from multiple threads trying to do this simultaneously. 认为我的错误源于试图同时执行此操作的多个线程。 The relevant sections are below. 相关部分如下。 I have a very limited understanding of how the overlays and such work on a low level, so I was wondering if anyone could confirm (or refute) that this could be causing issues. 我对叠加层和底层层的工作原理知之甚少,因此我想知道是否有人可以确认(或反驳)这可能会引起问题。

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

I tried making this method synchronized , but the error still occurred. 我尝试使此方法synchronized ,但是仍然发生错误。 Could this arise from the new runnable being pushed to the UI thread before the previous runnable terminates maybe? 这可能是由于新的可运行对象在先前的可运行对象终止之前被推送到UI线程吗? I've seen mention that populate is a better way than invalidate, although I'm not entirely sure how they're different. 我已经看到有人说填充是比使无效更好的方法,尽管我不完全确定它们有何不同。 Any ideas how to resolve this? 任何想法如何解决这个问题?

Modifying the set of overlays should always be done on the UI thread. 修改叠加层集应始终在UI线程上完成。 The List that getOverlays() returns is owned by the MapView , and it can decide to view or manipulate the list at any time. getOverlays()返回的ListMapView拥有,它可以随时决定查看或操作该列表。

Since you're working with a lot of geopoints, it's likely that your background thread is clearing (or adding) overlays while the MapView is iterating over them on the UI thread. 由于您正在使用许多地理位置,因此当MapView在UI线程上对其进行迭代时,您的后台线程可能正在清除(或添加)叠加层。 That would trigger a ConcurrentModificationException because the iterator is invalidated when its underlying set of overlays changes. 这将触发ConcurrentModificationException因为当其基础的叠加层集更改时,迭代器将无效。 Sometimes the changes are not immediately visible to the UI thread, so the crash is intermittent. 有时,更改不会立即显示在UI线程中,因此崩溃是间歇性的。

Setting up the overlays is usually the slow part of this type of workflow. 设置叠加层通常是此类工作流程中较慢的部分。 To avoid the concurrent modification, you could set up your overlays in the background thread and then make all of your calls to clear() and add() inside of the Runnable . 为了避免并发修改,您可以在后台线程中设置叠加层,然后在Runnable内部对clear()add()进行所有调用。 (Another option is to use an AsyncTask .) (另一种选择是使用AsyncTask 。)

For example: 例如:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 android:ConcurrentModificationException与地图覆盖 - android: ConcurrentModificationException with map overlays 从SolverEventListener修改Solution时,Optaplanner ConcurrentModificationException - Optaplanner ConcurrentModificationException when modifying Solution from SolverEventListener 更新叠加层时的MapView ConcurrentModificationException - MapView ConcurrentModificationException when updating overlays 了解并解决ConcurrentModificationException - Understanding and resolving ConcurrentModificationException ConcurrentModificationException *在*修改ArrayList之后 - ConcurrentModificationException *after* modifying ArrayList ConcurrentModificationException,无需修改对象 - ConcurrentModificationException without modifying object 不修改列表但仍然得到ConcurrentModificationException - Not modifying list but still get a ConcurrentModificationException 我不修改数组时出现ConcurrentModificationException吗? - ConcurrentModificationException when im not modifying the array? 修改多个地图时避免ConcurrentModificationException - Avoiding ConcurrentModificationException while modifying multiple Maps 在线程类中修改HashMap时获取ConcurrentModificationException - Getting ConcurrentModificationException while modifying a HashMap in a thread class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM