gpt4 book ai didi

android - 使用 mylocation 覆盖和计时器的 ConcurrentModificationException

转载 作者:行者123 更新时间:2023-11-29 22:26:43 25 4
gpt4 key购买 nike

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

好的,我的应用程序的一部分使用 Google Maps API 在 map 上显示叠加层(使用自定义叠加层类)以及使用 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异常在 java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)在 com.google.android.maps.OverlayBundle.draw(OverlayBundle.java:44)在 com.google.android.maps.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.ViewGroup.drawChild(ViewGroup.java:1640)在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)在 android.view.View.draw(View.java:6743)在 android.widget.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.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 方法)在 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(本地方法)

最佳答案

为什么要移除和替换叠加层?

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

您的错误肯定感觉像是与添加和删除叠加层有关。事实上,我想也许你在 doInBackground() 中这样做了,但你没有。因此,我认为从线程的角度来看,您正在做的事情是安全的,只是从处理的角度来看有点矫枉过正。

关于android - 使用 mylocation 覆盖和计时器的 ConcurrentModificationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5705463/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com