问题
I cannot figure out the origin of the ConcurrentModificationException
. In my activity
I'm calling
updateMapOverlay()
. I'm also calling updateMapOverlay()
inside another Thread (a TimerTask
) that is invoked on regular intervals. I'm taking the appropriate locks when invoking updateMapOverlay()
from both the threads. Is this problem being caused because I'm invoking updateMapOverlay
from inside a non-UI thread (i.e., TimerTask
). Has anyone else faced a similar issue ?
private void updateMapOverlay() {
this.itemizedOverlay.refreshItems(createOverlayItemsList());
List<Overlay> overlays = mapView.getOverlays();
overlays.clear();
overlays.add(cotItemizedOverlay);
this.mapview.invalidate();
}
Thanks.
Exception:
W/dalvikvm(10641): threadid=3: thread exiting with uncaught exception (group=0x4001b180)
E/AndroidRuntime(10641): Uncaught handler: thread main exiting due to uncaught exception
E/AndroidRuntime(10641): java.util.ConcurrentModificationException
E/AndroidRuntime(10641): at java.util.AbstractList$SimpleListIterator.next(AbstractList.java:64)
E/AndroidRuntime(10641): at com.google.android.maps.OverlayBundle.draw(OverlayBundle.java:41)
E/AndroidRuntime(10641): at com.google.android.maps.MapView.onDraw(MapView.java:494)
E/AndroidRuntime(10641): at android.view.View.draw(View.java:6535)
E/AndroidRuntime(10641): at android.view.ViewGroup.drawChild(ViewGroup.java:1531)
E/AndroidRuntime(10641): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
E/AndroidRuntime(10641): at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
E/AndroidRuntime(10641): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
E/AndroidRuntime(10641): at android.view.View.draw(View.java:6538)
E/AndroidRuntime(10641): at android.widget.FrameLayout.draw(FrameLayout.java:352)
E/AndroidRuntime(10641): at android.view.ViewGroup.drawChild(ViewGroup.java:1531)
E/AndroidRuntime(10641): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
E/AndroidRuntime(10641): at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
E/AndroidRuntime(10641): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
E/AndroidRuntime(10641): at android.view.View.draw(View.java:6538)
E/AndroidRuntime(10641): at android.widget.FrameLayout.draw(FrameLayout.java:352)
E/AndroidRuntime(10641): at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1830)
E/AndroidRuntime(10641): at android.view.ViewRoot.draw(ViewRoot.java:1349)
E/AndroidRuntime(10641): at android.view.ViewRoot.performTraversals(ViewRoot.java:1114)
E/AndroidRuntime(10641): at android.view.ViewRoot.handleMessage(ViewRoot.java:1633)
E/AndroidRuntime(10641): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(10641): at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime(10641): at android.app.ActivityThread.main(ActivityThread.java:4363)
E/AndroidRuntime(10641): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(10641): at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime(10641): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
E/AndroidRuntime(10641): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
E/AndroidRuntime(10641): at dalvik.system.NativeStart.main(Native Method)
I/Process ( 95): Sending signal. PID: 10641 SIG: 3
回答1:
Is this problem being caused because I'm invoking updateMapOverlay from inside a non-UI thread
Yes.
I'm also calling updateMapOverlay() inside another Thread (a TimerTask) that is invoked on regular intervals.
Why are you removing and adding an overlay constantly? Just update the overlay and invalidate. See here for an example of updating an overlay asynchronously.
回答2:
Thank you for your response.
However, in your code aren't you doing something similar (map.getOverlays().remove(sites);
and map.getOverlays().add(sites);
)?
class OverlayTask extends AsyncTask {
@Override
public void onPreExecute() {
if (sites!=null) {
map.getOverlays().remove(sites);
map.invalidate();
sites=null;
}
}
@Override
public Void doInBackground(Void... unused) {
SystemClock.sleep(5000); // simulated work
sites=new SitesOverlay();
return(null);
}
@Override public void onPostExecute(Void unused) { map.getOverlays().add(sites); map.invalidate(); } }
回答3:
Generally speaking you should be safe as long as you only modify your ItemizedOverlay's backing List/Map on the UI thread.
As Mark pointed out, AsyncTask's:
@Override
protected void onPostExecute(Cursor cursor) {
// modify List/Map
populate();
mapView.invalidate();
}
is always executed on the UI thread, so modifications are safe here.
回答4:
I'm having the same problem. To answer your question as to "why are you removing and adding an overlay constantly?", I'm doing it because some of my overlay items might no longer exist, or new ones might appear, and existing ones may change location, depending on what's happening in the rest of my particular application. Also, I've found no way of changing the location of an OverlayItem without extending it so that I can do so.
Besides, wouldn't changing what items are in the itemized overlay also cause a concurrent modification exception?
来源:https://stackoverflow.com/questions/2870743/android-2-1-googlemaps-itemizedoverlay-concurrentmodificationexception