更新叠加层时的MapView ConcurrentModificationException

时间:2012-02-12 19:07:59

标签: java android google-maps

我已经建立了谷歌api MapView演示。

我已经扩展了MapView类来创建一个类似于的“onPanListener”: How to catch that map panning and zoom are really finished?

我还创建了一个类似于的GroundOverlay类: Android google maps groundoverlay

我正在努力弄清楚为什么我有时会得到一个ConcurrentModificationException。我怀疑这可能是因为我最终导致两个定时器触发的panlisteneres执行并导致覆盖列表上的并发访问问题。但是,我不知道这是不是问题。我尝试在任何删除或添加任何内容的代码上添加synchronized(mapview.getOverlay()){}。

下面列出了我的堆栈跟踪,但我不确定该怎么做。看起来异常可能从我的GroundOverlay类中从draw方法开始(但我不确定)。当我删除地面覆盖时,我不会认为我得到了ConcurrentModificationException - 有点难以辨别,因为这是一个间歇性的事情。

堆栈跟踪似乎表明它来自mapview.draw方法。我想也许我可以在mapview子类中覆盖该方法并尝试同步它,但不幸的是,draw在父类中是最终的。同步dispatchDraw似乎没有帮助。

有没有更好的方法来调试这样的东西?也许以某种方式得到关于异常的更多信息 - 只要知道我的代码的哪一行就会引起极大的帮助。

我尝试过同步

02-12 10:59:31.995: E/AndroidRuntime(24649): FATAL EXCEPTION: main

02-12 10:59:31.995: E/AndroidRuntime(24649): java.util.ConcurrentModificationException
02-12 10:59:31.995: E/AndroidRuntime(24649):    at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:576)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at com.google.android.maps.OverlayBundle.draw(OverlayBundle.java:44)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at com.google.android.maps.MapView.onDraw(MapView.java:530)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at android.view.View.draw(View.java:6880)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at android.view.View.draw(View.java:6883)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at android.widget.FrameLayout.draw(FrameLayout.java:357)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at android.view.View.draw(View.java:6883)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at android.widget.FrameLayout.draw(FrameLayout.java:357)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2106)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at android.view.ViewRoot.draw(ViewRoot.java:1562)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at android.view.ViewRoot.performTraversals(ViewRoot.java:1298)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at android.view.ViewRoot.handleMessage(ViewRoot.java:1911)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at android.os.Handler.dispatchMessage(Handler.java:99)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at android.os.Looper.loop(Looper.java:130)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at android.app.ActivityThread.main(ActivityThread.java:3821)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at java.lang.reflect.Method.invokeNative(Native Method)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at java.lang.reflect.Method.invoke(Method.java:507)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
02-12 10:59:31.995: E/AndroidRuntime(24649):    at dalvik.system.NativeStart.main(Native Method)

这是我的OnChangeListener。根据评论,听起来像清除和重写叠加层不是最好的选择。也许,我应该从扩展的OverlayItem类中获取它,而不是试图从我的MapView类中获取onpan事件?我可以尝试一下。

mMapView.setOnChangeListener(new MyMapView.OnChangeListener() {

        @Override
        public void onChange(Metars metar, Pireps pirep, MyMapView view, GeoPoint newCenter, GeoPoint oldCenter,
                int newZoom, int oldZoom) {

            //metar.addOverlays(view);
            if (view.updatingOverlay == false) {
                view.updatingOverlay = true;
                synchronized (view.getOverlays() ) {
                    view.getOverlays().clear();
                    view.getOverlays().add(view.getRadar());
                }
                metar.addOverlays(view);
                pirep.addOverlays(view);
                view.postInvalidate();
                view.updatingOverlay = false;
            }


        }
    });

}

这是xxx.addOverlays(view)

的代码
public void addOverlays(MyMapView mapView) {

          // do a bunch of stuff and get overlays ready to add
    List<Overlay> mapOverlays = mapView.getOverlays();

    // add them to my subclass of ItemizedOverlay

    synchronized(mapOverlays) {
    if (itemizedoverlay.size() > 0 )
        mapOverlays.add(itemizedoverlay);
    }

}

1 个答案:

答案 0 :(得分:2)

通过更全面地阅读Android 2.1 GoogleMaps ItemizedOverlay ConcurrentModificationException之后,我得出的结论是,我的问题是我正在为计时器启动一个新线程,它添加和删除了覆盖项,这会间歇性地导致并发感知。< / p>

我最终将代码修改为Activity.runOnUiThread(...)中的覆盖,并且从那时起就没有看到问题。