>我已经清理了我的代码,以尽可能减少行数,但显示了我遇到的问题。
我的地图显示一些标记取决于相机位置。标记通过addMarker添加到地图上,并在HashMap中添加股票,其中Long用于获取标记和数据库记录之间的引用。
地图上的每个标记都包含一个标题和一个代码段,允许我显示 InfoWindow。在地图上,我有一个信息窗口点击监听器(标记标记);允许我向用户显示一个对话框,其中包含比信息窗口可以执行的更多的信息。侦听器参数中的标记与 HashMap 一起使用,以检索数据库记录的 id,以将其传递给对话框以检索对话框中的信息。
当用户在屏幕上移动时,通过检测标记是否始终在屏幕上或在移动后在屏幕外部,标记可能会被销毁。如果不是,我从哈希图中删除标记并使用 Marker.remove();将其从地图中删除的方法。
如果你幸运的话,所有这些都很好用。为什么?因为我发现地图似乎重用了已删除的标记(为什么不),但在某些情况下,addMarker 方法和传递给 onInfoWindowClickListener 的标记并不相同。比较参考不起作用,等于也不起作用。所以我无法使用这两种方法来比较哈希图和帕尔马斯中的标记。手动比较似乎是唯一的解决方案,但在执行此操作之前,我更愿意问您是否对正在发生的事情有任何想法。
我是否在下面的代码中犯了错误,或者它是 Maps API 的错误,它返回一个新标记但使用旧标记?真的是旧标记还是 API 中线程之间的同步问题?把它变成一个坏主意,有更好的解决方案吗?
我不知道,也许你有什么想法?
public class MainActivity extends FragmentActivity{
private enum CORNER {
TOP_LEFT,
TOP_RIGHT,
BOT_LEFT,
BOT_RIGHT
};
private GoogleMap map;
private SupportMapFragment mapFrag;
private Map<Long,Marker> markerMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
markerMap = new HashMap<Long, Marker>();
mapFrag = (SupportMapFragment)getSupportFragmentManager().findFragme ntById(R.id.maps_mv_map);
map = mapFrag.getMap();
map.setOnCameraChangeListener(new OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition position) {
addSiteOnMap();//update displayed marker
}
});
map.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {
@Override
public void onInfoWindowClick(Marker arg0) {
InformationDialog dialog = new InformationDialog();
Bundle args = new Bundle();
System.out.println(arg0);//show reference to the marker to find the problem
//retrieve the db Id depends on marker
for(Long key : markerMap.keySet())
{
if(markerMap.get(key).equals(arg0))
{
args.putLong("dbId",key);
break;
}
}
dialog.setArguments(args);
dialog.show(getSupportFragmentManager(), "information dialog");
}
});
}
//get the LatLng for a corner
private LatLng getCorner(CORNER corner)
{
int height = 0;
int width = 0;
if(corner == CORNER.BOT_LEFT || corner == CORNER.BOT_RIGHT)
height = mapFrag.getView().getHeight();
if(corner == CORNER.BOT_RIGHT || corner == CORNER.TOP_RIGHT)
width = mapFrag.getView().getWidth();
com.google.android.gms.maps.Projection pr = map.getProjection();
return pr.fromScreenLocation(new Point(width,height));
}
private void addSitesOnMap()
{
List<Data> list = Database.getInstance(this).getData(getCorner(CORNER.TOP_RIGHT),getCorner(CORNER.BOT_LEFT));
Set<Long> keys = markerMap.keySet();
List<Long> idList = new ArrayList<Long>();
for(Data site : list)
{
idList.add(site.getDbId());
}
keys.retainAll(idList);
Set<Long> oldKeys = markerMap.keySet();
for(Long id : oldKeys)
{
if(!keys.contains(id))
{
Marker marker = markerMap.remove(id);
marker.remove();
}
}
for(Data site : list)
{
if(!markerMap.containsKey(site.getDbId()))//if the marker is not already display on the map
{
MarkerOptions options = new MarkerOptions();
options.position(site.getLoc());
options.title(site.getCityName());
DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, Locale.getDefault());
options.snippet(df.format(site.getDate().getTime()));
Bitmap bp = BitmapFactory.decodeResource(getResources(), R.drawable.marker);
options.icon(BitmapDescriptorFactory.fromBitmap(bp));
markerMap.put(Long.valueOf(site.getDbId()),map.addMarker(options));
}
}
for(Long key : markerMap.keySet())
{
System.out.println(markerMap.get(key).getTitle()+" "+key+" "+markerLi st.get(key));//show reference to the all marker in the map and information to help me find what reference is interesting for me
}
}
}
感谢您的帮助
根据 Java 文档 : keySet() "返回此映射中包含的键的 Set 视图。该集由地图支持,因此对地图的更改会反映在集合中,反之亦然。(来源)
问题出在以下代码段中:
List<Data> list = Database.getInstance(this).getData(getCorner(CORNER.TOP_RIGHT),getCorner(CORNER.BOT_LEFT));
Set<Long> keys = markerMap.keySet();
List<Long> idList = new ArrayList<Long>();
for(Data site : list) {
idList.add(site.getDbId());
}
// Here, you drop all ids that are not visible anymore
// but before you had a chance to remove the marker
keys.retainAll(idList);
在摆弄密钥集之前,您可能需要复制它。你所谓的 oldKeys 实际上是 newKeys。