1

这个问题一直困扰着我,希望您能提供帮助!我以前在这里找到了许多问题的答案,希望你们能再次发挥你的魔力:)

好的,所以我的应用程序的一部分使用 Google Maps API 在地图上显示覆盖(使用自定义覆盖类)以及使用 mylocationoverlay 的用户位置。现在,如果我不激活 mylocationoverlay 一切正常,但如果它被激活,则应用程序强制以ConcurrentModificationException.

现在计时器用于刷新覆盖,因为它的位置总是在变化。为此,我使用了一个异步任务来删除覆盖并添加一个具有更新位置的新覆盖。我是否正确假设 mylocationoverlay 在后台做类似的事情?如果该假设有效,那么我得出的结论是 mylocationoverlay 和我的异步任务正在尝试同时迭代/修改同一个数组。唯一的就是,我不知道如何阻止这种情况发生!

我真的不能在这里发布我的代码,因为它非常大,但我使用了一个从 github 创建的由 commonsguy 创建的示例代码,并对其进行了修改以产生相同的问题。

任何帮助将不胜感激,因为这真的让我很沮丧。在此先感谢,并为冗长的描述感到抱歉!

编辑:commonsguy 代码的链接是 - https://github.com/commonsguy/cw-advandroid/blob/master/Maps/NooYawkAsync/

编辑 2:在 java 代码之后添加了错误跟踪。

package com.commonsware.android.maps;

import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.OverlayItem;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class NooYawk extends MapActivity {
    private MapView map=null;
    private MyLocationOverlay me=null;
    private SitesOverlay sites=null;
    public Timer timer;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        map=(MapView)findViewById(R.id.map);

        map.getController().setCenter(getPoint(40.76793169992044, -73.98180484771729));
        map.getController().setZoom(17);
        map.setBuiltInZoomControls(true);

        me=new MyLocationOverlay(this, map);
        me.enableMyLocation();
        map.getOverlays().add(me);

        timer = new Timer();
        timer.scheduleAtFixedRate(new RemindTask(), 10000, 10000);

        new OverlayTask().execute();
    }

    @Override
    public void onResume() {
        super.onResume();
        me.enableMyLocation();
        me.enableCompass();
    }       

    @Override
    public void onPause() {
        super.onPause();
        me.disableMyLocation();
        me.disableCompass();
    }       

    @Override
    protected boolean isRouteDisplayed() {
        return(false);
    }

    private GeoPoint getPoint(double lat, double lon) {
        return(new GeoPoint((int)(lat*1000000.0), (int)(lon*1000000.0)));
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////// TIMER CLASS //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class RemindTask extends TimerTask {
    public void run() {
        new OverlayTask().execute();
    }
}


    private class SitesOverlay extends ItemizedOverlay<CustomItem> {
        private Drawable heart=null;
        private List<CustomItem> items=new ArrayList<CustomItem>();

        public SitesOverlay() {
            super(null);

            heart=getMarker(R.drawable.heart_full);

            items.add(new CustomItem(getPoint(40.748963847316034, -73.96807193756104),
                                                "UN", "United Nations", getMarker(R.drawable.blue_full_marker), heart));
            populate();
        }

        @Override
        protected CustomItem createItem(int i) {
            return(items.get(i));
        }

        @Override
        public void draw(Canvas canvas, MapView mapView, boolean shadow) {
            super.draw(canvas, mapView, shadow);

        }

        @Override
        public int size() {
            return(items.size());
        }

        void toggleHeart() {
            CustomItem focus=getFocus();

            if (focus!=null) {
                focus.toggleHeart();
            }

            map.invalidate();
        }

        private Drawable getMarker(int resource) {
            Drawable marker=getResources().getDrawable(resource);

            marker.setBounds(0, 0, marker.getIntrinsicWidth(), marker.getIntrinsicHeight());
            boundCenter(marker);

            return(marker);
        }
    }

    class PopupPanel {
        View popup;
        boolean isVisible=false;

        PopupPanel(int layout) {
            ViewGroup parent=(ViewGroup)map.getParent();

            popup=getLayoutInflater().inflate(layout, parent, false);

            popup.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    hide();
                }
            });
        }

        View getView() {
            return(popup);
        }

        void show(boolean alignTop) {
            RelativeLayout.LayoutParams lp=new RelativeLayout.LayoutParams(
                        RelativeLayout.LayoutParams.WRAP_CONTENT,
                        RelativeLayout.LayoutParams.WRAP_CONTENT
            );

            if (alignTop) {
                lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
                lp.setMargins(0, 20, 0, 0);
            }
            else {
                lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
                lp.setMargins(0, 0, 0, 60);
            }

            hide();

            ((ViewGroup)map.getParent()).addView(popup, lp);
            isVisible=true;
        }

        void hide() {
            if (isVisible) {
                isVisible=false;
                ((ViewGroup)popup.getParent()).removeView(popup);
            }
        }
    }

    class CustomItem extends OverlayItem {
        Drawable marker=null;
        boolean isHeart=false;
        Drawable heart=null;

        CustomItem(GeoPoint pt, String name, String snippet, Drawable marker, Drawable heart) {
            super(pt, name, snippet);

            this.marker=marker;
            this.heart=heart;
        }

        @Override
        public Drawable getMarker(int stateBitset) {
            Drawable result=(isHeart ? heart : marker);

            setState(result, stateBitset);

            return(result);
        }

        void toggleHeart() {
            isHeart=!isHeart;
        }
    }

    class OverlayTask extends AsyncTask<Void, Void, Void> {
        @Override
        public void onPreExecute() {
            if (sites!=null) {
                map.getOverlays().remove(sites);
                map.postInvalidate();   
                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.postInvalidate();           
        }
    }
}

堆栈跟踪:

com.google.android.maps.OverlayBundle.draw(OverlayBundle.java:44) 的 com.google.android.maps 的 java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573) 的 java.util.ConcurrentModificationException。 MapView.onDraw(MapView.java:494) 在 android.view.View.draw(View.java:6740) 在 android.view.ViewGroup.drawChild(ViewGroup.java:1640) 在 android.view.ViewGroup.dispatchDraw(ViewGroup .java:1367) 在 android.view.ViewGroup.drawChild(ViewGroup.java:1638) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) 在 android.view.ViewGroup.drawChild(ViewGroup.java:1638)在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) 在 android.view.View.draw(View.java:6743) 在 android.widget.FrameLayout.draw(FrameLayout.java:352) 在 android.view。 android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) 上的 ViewGroup.drawChild(ViewGroup.java:1640)。view.View.draw(View.java:6743) at android.widget.FrameLayout.draw(FrameLayout.java:352) at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1847)在 android.view.ViewRoot.draw(ViewRoot.java:1407) 在 android.view.ViewRoot.performTraversals(ViewRoot.java:1163) 在 android.view.ViewRoot.handleMessage(ViewRoot.java:1727) 在 android.os。 Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java:123) 在 android.app.ActivityThread.main(ActivityThread.java:4627) 在 java.lang.reflect.Method.invokeNative (Native Method) at java.lang.reflect.Method.invoke(Method.java:521) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878) at com.android.internal.os .ZygoteInit.main(ZygoteInit.java:636) 在 dalvik.system.NativeStart.main(Native Method)FrameLayout.draw(FrameLayout.java:352) 在 com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1847) 在 android.view.ViewRoot.draw(ViewRoot.java:1407) 在 android .view.ViewRoot.performTraversals(ViewRoot.java:1163) 在 android.os.Looper 的 android.view.ViewRoot.handleMessage(ViewRoot.java:1727) 在 android.os.Handler.dispatchMessage(Handler.java:99)。 loop(Looper.java:123) 在 android.app.ActivityThread.main(ActivityThread.java:4627) 在 java.lang.reflect.Method.invokeNative(Native Method) 在 java.lang.reflect.Method.invoke(Method. java:521) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636) 在 dalvik.system.NativeStart .main(本机方法)FrameLayout.draw(FrameLayout.java:352) 在 com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1847) 在 android.view.ViewRoot.draw(ViewRoot.java:1407) 在 android .view.ViewRoot.performTraversals(ViewRoot.java:1163) 在 android.os.Looper 的 android.view.ViewRoot.handleMessage(ViewRoot.java:1727) 在 android.os.Handler.dispatchMessage(Handler.java:99)。 loop(Looper.java:123) 在 android.app.ActivityThread.main(ActivityThread.java:4627) 在 java.lang.reflect.Method.invokeNative(Native Method) 在 java.lang.reflect.Method.invoke(Method. java:521) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636) 在 dalvik.system.NativeStart .main(本机方法)draw(PhoneWindow.java:1847) at android.view.ViewRoot.draw(ViewRoot.java:1407) at android.view.ViewRoot.performTraversals(ViewRoot.java:1163) at android.view.ViewRoot.handleMessage(ViewRoot.java :1727) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java:123) 在 android.app.ActivityThread.main(ActivityThread.java:4627) 在 java .lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:521) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)在 dalvik.system.NativeStart.main(本机方法)的 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)draw(PhoneWindow.java:1847) at android.view.ViewRoot.draw(ViewRoot.java:1407) at android.view.ViewRoot.performTraversals(ViewRoot.java:1163) at android.view.ViewRoot.handleMessage(ViewRoot.java :1727) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java:123) 在 android.app.ActivityThread.main(ActivityThread.java:4627) 在 java .lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:521) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)在 dalvik.system.NativeStart.main(本机方法)的 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)1727) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java:123) 在 android.app.ActivityThread.main(ActivityThread.java:4627) 在 java. lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:521) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636) 在 dalvik.system.NativeStart.main(Native Method)1727) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java:123) 在 android.app.ActivityThread.main(ActivityThread.java:4627) 在 java. lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:521) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636) 在 dalvik.system.NativeStart.main(Native Method)main(ZygoteInit.java:636) 在 dalvik.system.NativeStart.main(Native Method)main(ZygoteInit.java:636) 在 dalvik.system.NativeStart.main(Native Method)

4

1 回答 1

2

为什么要移除和更换覆盖层?

为什么不单独留下叠加层并更改其标记?只需populate()再次调用它,ItemizedOverlay它就会再次调用。请务必返回新的正确数据。size()getItem()

您的错误绝对感觉像是与添加和删除叠加层有关。事实上,我以为你可能在 中这样做doInBackground(),但你不是。因此,我会认为从线程的角度来看你正在做的事情是安全的,从处理的角度来看只是矫枉过正。

于 2011-04-24T11:28:45.793 回答