Android并发修改错误MapOverlays

时间:2013-01-24 22:34:50

标签: android android-mapview concurrentmodification

在我的应用程序中,我有一个带有自定义MapOverlays的MapView。

我已经覆盖了onDraw方法,因此我可以对位于相同位置的叠加项进行聚类 - 并且效果很好。

我现在正在尝试添加一大堆标记,虽然我已经同步了方法和正确的对象但我得到了Concurrent Modification Error

我认为它与onDraw方法有关,每次需要时都会多次调用(在某些线程中可以读取) - 并且它必须在尝试的同时更新ArrayList迭代它。

我的问题是为什么?我确实同步了......它应该被锁定..

我的函数是从onDraw()调用的:

private synchronized ArrayList<OverlayItem> createOverlayItems(MapView mapView)
    {
        Projection projection = mapView.getProjection();
        int minPixelDistance = app.getPixels(50); //distance allowed between 2 markers      
        synchronized (fullMapOverlays) {
            OverlayItem me = getOverlayItem(ME);
            fullMapOverlays.remove(me);
            mapOverlays.clear();
            mapOverlays.addAll(fullMapOverlays);
            Iterator<OverlayItem> overlayIterator = fullMapOverlays.iterator();
            while (overlayIterator.hasNext())
            {   
                OverlayItem item = overlayIterator.next();
                Point currentItemPoint = projection.toPixels(item.getPoint(), null);
                if (!isPointInScreen(currentItemPoint))
                    continue;
                else if (item.getTitle().equals(ME) && item.getSnippet().equals(ME))
                    continue;
                else if (!mapOverlays.contains(item))
                    continue;

                cluster.clear();
                Iterator<OverlayItem> innerIterator = mapOverlays.iterator();
                while (innerIterator.hasNext())
                {
                    OverlayItem itemToCheck = innerIterator.next();
                    Point checkingItemPoint = projection.toPixels(itemToCheck.getPoint(), null);
                    if (!isPointInScreen(checkingItemPoint))
                    {
                        innerIterator.remove();
                        continue;
                    }
                    else if (itemToCheck.getTitle().equals(ME) && itemToCheck.getSnippet().equals(ME))
                        continue;
                    else if  (itemToCheck.getTitle().equals(CLUSTER))
                        continue;               

                    if (!item.equals(itemToCheck))
                    {
                        if (getPixelsDistance(currentItemPoint, checkingItemPoint) <= minPixelDistance)
                        {
                            cluster.add(itemToCheck);
                            innerIterator.remove();
                        }
                    }
                }           
                if (cluster.size() > 0)
                {
                    mapOverlays.remove(item);
                    cluster.add(item);              
                    String itemsTitle = "";
                    for (int i=0; i<cluster.size(); i++)
                    {
                        if (i == 0)
                            itemsTitle += cluster.get(i).getTitle();
                        else
                            itemsTitle += "|" + cluster.get(i).getTitle();
                    }
                    OverlayItem clusterItem = new OverlayItem(cluster.get(0).getPoint(), CLUSTER, itemsTitle);
                    clusterItem.setMarker(boundCenterBottom(createClusterDrawable(cluster.size())));
                    mapOverlays.add(clusterItem);               
                }
            }       
            fullMapOverlays.add(fullMapOverlays.size(), me);
            mapOverlays.add(mapOverlays.size(), me);            
        }
        return mapOverlays;
    }

可爱的logcat:

01-25 00:27:47.070: W/System.err(4676): java.util.ConcurrentModificationException
01-25 00:27:47.070: W/System.err(4676):     at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:576)
01-25 00:27:47.070: W/System.err(4676):     at com.WhosAround.Activities.Map.MapOverlay.createOverlayItems(MapOverlay.java:169)
01-25 00:27:47.070: W/System.err(4676):     at com.WhosAround.Activities.Map.MapOverlay.draw(MapOverlay.java:61)
01-25 00:27:47.070: W/System.err(4676):     at com.google.android.maps.Overlay.draw(Overlay.java:179)
01-25 00:27:47.075: W/System.err(4676):     at com.google.android.maps.OverlayBundle.draw(OverlayBundle.java:42)
01-25 00:27:47.075: W/System.err(4676):     at com.google.android.maps.MapView.onDraw(MapView.java:530)
01-25 00:27:47.075: W/System.err(4676):     at android.view.View.draw(View.java:6933)
01-25 00:27:47.075: W/System.err(4676):     at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
01-25 00:27:47.075: W/System.err(4676):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
01-25 00:27:47.075: W/System.err(4676):     at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
01-25 00:27:47.075: W/System.err(4676):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
01-25 00:27:47.075: W/System.err(4676):     at android.view.View.draw(View.java:6936)
01-25 00:27:47.075: W/System.err(4676):     at android.widget.FrameLayout.draw(FrameLayout.java:357)
01-25 00:27:47.075: W/System.err(4676):     at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
01-25 00:27:47.075: W/System.err(4676):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
01-25 00:27:47.075: W/System.err(4676):     at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
01-25 00:27:47.075: W/System.err(4676):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
01-25 00:27:47.075: W/System.err(4676):     at android.view.View.draw(View.java:6936)
01-25 00:27:47.075: W/System.err(4676):     at android.widget.FrameLayout.draw(FrameLayout.java:357)
01-25 00:27:47.075: W/System.err(4676):     at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
01-25 00:27:47.075: W/System.err(4676):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
01-25 00:27:47.075: W/System.err(4676):     at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
01-25 00:27:47.075: W/System.err(4676):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
01-25 00:27:47.075: W/System.err(4676):     at android.view.View.draw(View.java:6936)
01-25 00:27:47.075: W/System.err(4676):     at android.widget.FrameLayout.draw(FrameLayout.java:357)
01-25 00:27:47.075: W/System.err(4676):     at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
01-25 00:27:47.075: W/System.err(4676):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
01-25 00:27:47.075: W/System.err(4676):     at android.view.View.draw(View.java:6936)
01-25 00:27:47.075: W/System.err(4676):     at android.widget.FrameLayout.draw(FrameLayout.java:357)
01-25 00:27:47.075: W/System.err(4676):     at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1917)
01-25 00:27:47.075: W/System.err(4676):     at android.view.ViewRoot.draw(ViewRoot.java:1530)
01-25 00:27:47.075: W/System.err(4676):     at android.view.ViewRoot.performTraversals(ViewRoot.java:1266)
01-25 00:27:47.080: W/System.err(4676):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1868)
01-25 00:27:47.080: W/System.err(4676):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-25 00:27:47.080: W/System.err(4676):     at android.os.Looper.loop(Looper.java:130)
01-25 00:27:47.080: W/System.err(4676):     at android.app.ActivityThread.main(ActivityThread.java:3691)
01-25 00:27:47.080: W/System.err(4676):     at java.lang.reflect.Method.invokeNative(Native Method)
01-25 00:27:47.080: W/System.err(4676):     at java.lang.reflect.Method.invoke(Method.java:507)
01-25 00:27:47.080: W/System.err(4676):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:907)
01-25 00:27:47.080: W/System.err(4676):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:665)
01-25 00:27:47.080: W/System.err(4676):     at dalvik.system.NativeStart.main(Native Method)

2 个答案:

答案 0 :(得分:1)

确定找到了,我从另一个Thread更新了MapActivity ....

您必须确保从UI线程添加OverlayItems。

答案 1 :(得分:0)

mapOverlays.remove(项目);看起来像是我的罪魁祸首。如果在迭代列表时直接删除项目,则会导致并发修改。

使用迭代器删除内容而不是直接删除。