java.util.ConcurrentModificationException在MapView上

时间:2012-02-17 09:55:40

标签: android android-mapview java.util.concurrent concurrentmodification

家伙

我很多天都面临着非常奇怪的问题。我正在尝试频繁更新叠加层。所以有时我在地图上触摸时会得到“java.util.ConcurrentModificationException”,或者当地图试图更新叠加时有时会得到但是我找不到完整的线路,这个错误即将到来。

02-17 14:56:01.621: W/dalvikvm(3653): threadid=1: thread exiting with uncaught exception (group=0x40015560)
02-17 14:56:01.631: E/AndroidRuntime(3653): FATAL EXCEPTION: main
02-17 14:56:01.631: E/AndroidRuntime(3653): java.util.ConcurrentModificationException
02-17 14:56:01.631: E/AndroidRuntime(3653):     at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:576)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at com.google.android.maps.OverlayBundle.draw(OverlayBundle.java:41)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at com.google.android.maps.MapView.onDraw(MapView.java:530)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.view.View.draw(View.java:6880)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.view.View.draw(View.java:6883)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.widget.FrameLayout.draw(FrameLayout.java:357)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.view.View.draw(View.java:6883)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.widget.FrameLayout.draw(FrameLayout.java:357)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.view.View.draw(View.java:6883)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.widget.FrameLayout.draw(FrameLayout.java:357)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1862)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.view.ViewRoot.draw(ViewRoot.java:1522)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.view.ViewRoot.performTraversals(ViewRoot.java:1258)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1859)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.os.Handler.dispatchMessage(Handler.java:99)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.os.Looper.loop(Looper.java:130)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at android.app.ActivityThread.main(ActivityThread.java:3683)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at java.lang.reflect.Method.invokeNative(Native Method)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at java.lang.reflect.Method.invoke(Method.java:507)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
02-17 14:56:01.631: E/AndroidRuntime(3653):     at dalvik.system.NativeStart.main(Native Method)

我正在使用Balloon Overlay

我认为它会在"mapview.getOverlay()"上抛出错误,因为它在1秒内调用了4-5次..

谢谢,

CapDroid

这里是代码流程.. 我的线程代码....

Thread connection = new Thread(){
        public void run() {
            try {

                while (my condition)
                {
                    try 
                    {
                                        //This method should be call every seconds
                        updateMethod();
                    } 
                    catch (Exception e) 
                    {
                        e.printStackTrace();
                        break;
                    }
                } 
            } 
            catch (Exception e) 
            {

            }
        }
    };

这是我的updateMethod(); 在这段代码中,hashmapOverlay是HashMap,如下所示

 public static Map<String,MyItemizedOverlay> hashmapOverlay;

 public void updateMethod()
{

                    if(hashmapOverlay.containsKey(id))
                        {
                            mapview.getOverlays().remove(hashmapOnlineFriendsOverlay.get(id));
                        }
                    MyItemizedOverlay mMyItemizedOverlay = new MyItemizedOverlay(drawable, mapview);
                        OverlayItem overlayItem = new OverlayItem(gp,title ,snippet);
                        mMyItemizedOverlay.addOverlay(overlayItem); 
                    hashmapOverlay.put(id, mMyItemizedOverlay);
                    addOverlayMethod(mActivity, mapView, mMyItemizedOverlay);   

}

这是我的addOverlayMethod

addOverlayMethod(Activity mActivity, final MapView mapView, final Object mObject)
{
    mActivity.runOnUiThread(new Runnable(){

        @Override
        public void run()
        {

                try {
                    MyItemizedOverlay overlay = (MyItemizedOverlay) mObject;
                    mapView.getOverlays().add(overlay);
                } catch (Exception e)
                {}              

        }
    });
}

5 个答案:

答案 0 :(得分:2)

为避免ConcurrentModificationException在以下任何情况下复制您的收藏集:

  • 在迭代集合之前
  • 在将其传递给API之前
乍一看,这看起来有点矫枉过正,但以后会为你节省很多麻烦。复制很简单,只需拨打new ArrayList<YourClass>(existingList)

答案 1 :(得分:1)

我认为您使用Thread及其创建Concurrency因此在您的运行方法中使用Syncronized(MainActivity.this) ....并使用向量而不是列表因为向量是同步的...其工作对我来说......

答案 2 :(得分:1)

好吧,似乎在您的updateMethod()中,您仍然试图Update来自Non-UI主题的用户界面<{1}}

mapview.getOverlays().remove(hashmapOnlineFriendsOverlay.get(id));

因此,尝试在RunOnUiThread内执行此部分代码并尝试。希望这会奏效。

UPDATE:

此外,为什么您尝试addremove Overlay所有内容,您不需要这样做只是尝试更新Overlay和{{ 1}}它。 Have a look at this example.

答案 3 :(得分:1)

我不确定叠加管理,但是我看到它的方式,你在非UI线程(在UpdateMethod中)使用HashMap.put修改你的HashMap,当毫无疑问被迭代或使用时应用程序中的其他位置 - 可能在您移动地图时仍然请求新的叠加层。

如果您阅读docs,它会说这会导致ConcurrentModificationException。相反,请尝试使用ConcurrentHashMap,或重新构建代码以更新正在使用它的主线程上的hashmap。

答案 4 :(得分:1)

是的,你可以做一些工作, 步骤如下。

  1. 制作Pendingnotification类(修改细节)。
  2. 列出Pendingnotification。
  3. 当任何通知收到dnt直接修改它时,收集所有修改并放入堆栈(Pendingnotification类)即。将其添加到Pendingnotification列表中。
  4. 现在逐个修改对象,并在完成工作时删除相同的对象。
  5. 相同的方式,直到Pendingnotification List变为空。

    另请注意,必须在UI Thread中执行任何修改,而不是NonUI Thread