我已经建立了谷歌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);
}
}
答案 0 :(得分:2)
通过更全面地阅读Android 2.1 GoogleMaps ItemizedOverlay ConcurrentModificationException之后,我得出的结论是,我的问题是我正在为计时器启动一个新线程,它添加和删除了覆盖项,这会间歇性地导致并发感知。< / p>
我最终将代码修改为Activity.runOnUiThread(...)中的覆盖,并且从那时起就没有看到问题。