1

この問題は私の頭を悩ませてきました、そしてあなたが助けてくれることを願っています!私は以前にここで多くの問題に対する答えを見つけました、そしてあなたの人々があなたの魔法を再び働かせることを願っています:)

さて、私のアプリの一部はGoogle Maps APIを使用して、地図上にオーバーレイを表示し(カスタムオーバーレイクラスを使用)、mylocationoverlayを使用してユーザーの場所を表示します。mylocationoverlayをアクティブにしないと、すべてが正常に機能しますが、アクティブにすると、アプリの強制は。で閉じますConcurrentModificationException

オーバーレイの位置は常に変化するため、タイマーを使用してオーバーレイを更新します。このために、非同期タスクを使用してオーバーレイを削除し、更新された位置で新しいオーバーレイを追加しました。mylocationoverlayがバックグラウンドで同様のことを行うと仮定するのは正しいですか?その仮定が有効である場合、mylocationoverlayと非同期タスクが同じ配列を同時に反復/変更しようとしているという結論に達しました。唯一これは、これが起こらないようにする方法がわかりません!

コードが非常に大きいため、ここに実際に投稿することはできませんが、commonsguyによって作成されたgithubから取得したサンプルコードを使用し、同じ問題が発生するように変更しました。

これは本当に私を苛立たせているので、どんな助けでも大歓迎です。事前に感謝し、長い説明をお詫びします!

編集: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();           
        }
    }
}

スタックトレース:

java.util.ConcurrentModificationException at java.util.ArrayList $ ArrayListIterator.next(ArrayList.java:573)at com.google.android.maps.OverlayBundle.draw(OverlayBundle.java:44)atcom.google.android.maps。 MapView.onDraw(MapView.java:494)at android.view.View.draw(View.java:6740)at android.view.ViewGroup.drawChild(ViewGroup.java:1640)at android.view.ViewGroup.dispatchDraw(ViewGroup .java:1367)at android.view.ViewGroup.drawChild(ViewGroup.java:1638)at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)at android.view.ViewGroup.drawChild(ViewGroup.java:1638) android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)at android.view.View.draw(View.java:6743)at android.widget.FrameLayout.draw(FrameLayout.java:352)atandroid.view。 android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)のViewGroup.drawChild(ViewGroup.java:1640)android。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)at android.view.ViewRoot.performTraversals(ViewRoot.java:1163)at android.view.ViewRoot.handleMessage(ViewRoot.java:1727)atandroid.os。 Handler.dispatchMessage(Handler.java:99)at android.os.Looper.loop(Looper.java:123)at android.app.ActivityThread.main(ActivityThread.java:4627)at java.lang.reflect.Method.invokeNative (ネイティブメソッド)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)at dalvik.system.NativeStart.main(ネイティブメソッド)FrameLayout.draw(FrameLayout.java:352)at com.android.internal.policy.impl.PhoneWindow $ DecorView.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)at android.os.Handler.dispatchMessage(Handler.java:99)atandroid.os.Looper。 loop(Looper.java:123)at android.app.ActivityThread.main(ActivityThread.java:4627)at 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)at dalvik.system.NativeStart .main(ネイティブメソッド)FrameLayout.draw(FrameLayout.java:352)at com.android.internal.policy.impl.PhoneWindow $ DecorView.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)at android.os.Handler.dispatchMessage(Handler.java:99)atandroid.os.Looper。 loop(Looper.java:123)at android.app.ActivityThread.main(ActivityThread.java:4627)at 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)at 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)at android.os.Looper.loop(Looper.java:123)at android.app.ActivityThread.main(ActivityThread.java:4627)at 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) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)at 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)at android.os.Looper.loop(Looper.java:123)at android.app.ActivityThread.main(ActivityThread.java:4627)at 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) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)at dalvik.system.NativeStart.main(ネイティブメソッド)1727)android.os.Handler.dispatchMessage(Handler.java:99)at android.os.Looper.loop(Looper.java:123)at android.app.ActivityThread.main(ActivityThread.java:4627)atjava。 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)at dalvik.system.NativeStart.main(ネイティブメソッド)1727)android.os.Handler.dispatchMessage(Handler.java:99)at android.os.Looper.loop(Looper.java:123)at android.app.ActivityThread.main(ActivityThread.java:4627)atjava。 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)at dalvik.system.NativeStart.main(ネイティブメソッド)main(ZygoteInit.java:636)at dalvik.system.NativeStart.main(ネイティブメソッド)main(ZygoteInit.java:636)at dalvik.system.NativeStart.main(ネイティブメソッド)

4

1 に答える 1

2

なぜオーバーレイを削除して交換するのですか?

オーバーレイをそのままにして、マーカーを変更してみませんか?populate()をもう一度呼び出すと、何度もItemizedOverlay呼び出されます。必ず新しい正しいデータを返してください。size()getItem()

エラーは、オーバーレイの追加と削除に関連しているように感じます。実際、おそらくあなたはでそうしていると思いましたがdoInBackground()、そうではありません。したがって、私は、あなたがしていることは、スレッドの観点からは安全であり、処理の観点からはやり過ぎだと思っていたでしょう。

于 2011-04-24T11:28:45.793 に答える