点击地图标记后Material对话框仅显示数组列表最后一项问题求助
解决地图标记点击后Material对话框仅显示数组最后一项的问题
嗨,这个问题我太熟了!之前做地图相关功能时踩过一模一样的坑,核心原因是Java循环里的变量捕获机制搞的鬼,我给你拆解清楚,再给你两种靠谱的解决方案:
问题根源
当你在循环遍历drivers列表、给每个Marker绑定点击监听时,如果直接在监听里引用循环中的driver变量(或者循环索引i),这个变量并不是有效final的。等用户点击Marker的时候,循环早就跑完了,这个变量会指向循环的最后一个元素,所以不管点哪个Marker,对话框都会显示最后一个驾驶员的数据。
解决方案
方案1:用临时final变量固定当前实例
在循环内部,把当前遍历到的Driver对象赋值给一个final的临时变量,这样每个Marker的点击监听都会捕获到属于自己的独立实例,不会被后续循环覆盖:
// 假设你在获取drivers数据后的循环逻辑 for (int i = 0; i < drivers.size(); i++) { // 关键:把当前driver存到final变量里,每个监听拿自己的实例 final Driver currentDriver = drivers.get(i); // 添加地图标记 Marker marker = mMap.addMarker(new MarkerOptions() .position(new LatLng(currentDriver.getLat(), currentDriver.getLng())) .title(currentDriver.getName())); // 绑定点击监听 marker.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() { @Override public boolean onMarkerClick(Marker marker) { // 这里用currentDriver就不会出问题啦 new MaterialDialog.Builder(MainActivity.this) .title(currentDriver.getName()) .content("驾驶员ID:" + currentDriver.getId() + "\n位置:" + currentDriver.getLat() + "," + currentDriver.getLng()) .show(); return true; } }); }
方案2:用Marker的Tag存储Driver对象
另一种更灵活的方式,把Driver对象直接绑定到Marker的tag属性上,点击时从Marker里取出对应的对象,完全避开变量捕获的问题:
for (int i = 0; i < drivers.size(); i++) { Driver driver = drivers.get(i); Marker marker = mMap.addMarker(new MarkerOptions() .position(new LatLng(driver.getLat(), driver.getLng())) .title(driver.getName())); // 把Driver对象存入Marker的Tag marker.setTag(driver); marker.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() { @Override public boolean onMarkerClick(Marker marker) { // 从Tag里取出对应的Driver实例 Driver clickedDriver = (Driver) marker.getTag(); if (clickedDriver != null) { new MaterialDialog.Builder(MainActivity.this) .title(clickedDriver.getName()) .content("驾驶员ID:" + clickedDriver.getId() + "\n位置:" + clickedDriver.getLat() + "," + clickedDriver.getLng()) .show(); } return true; } }); }
两种方案都能解决问题,个人更推荐方案2——后续如果需要修改驾驶员数据,或者给Marker绑定更多额外信息,通过Tag管理会更清晰。
内容的提问来源于stack exchange,提问作者Fred Adu
相关产品推荐
相关产品推荐

