Android遍历列表移除Google Map标记:Firebase离线用户标记未删除
问题根因
你的代码核心逻辑错误出在onDataChange回调的开头:每次数据库数据变更触发回调时,你都直接重新初始化了activeMarkers为空列表,之后仅往这个新列表里添加了当前在线用户的标记。等到你执行离线用户标记移除逻辑时,activeMarkers里根本不存在离线用户对应的标记引用,自然找不到也删不了原有标记。
同时你的实现还有三个隐性问题:
- 每次数据更新都会给所有在线用户重复叠加新标记,同一个位置会堆叠多个重复标记
- 标记的title错误设置为当前登录用户的昵称,而非对应用户自身的昵称
- 正序遍历列表删除元素时会出现下标偏移,可能漏删符合条件的条目
修复方案
- 将
activeMarkers改为Activity的全局成员变量,不要在onDataChange内部重复初始化 - 调整
onDataChange内的执行逻辑顺序:先处理离线用户移除,再处理在线用户的新增/位置更新 - 遍历删除列表元素时用倒序遍历避免漏删
以下是修正后的代码示例:
// 把activeMarkers移到Activity的成员变量位置,不要写在ValueEventListener内部 private List<Pair<String, Marker>> activeMarkers = new ArrayList<>(); // onMapReady内的监听器代码调整为如下 FirebaseDatabase.getInstance().getReference().child("users").addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { List<User> onlineUsers = new ArrayList<>(); List<User> offlineUsers = new ArrayList<>(); // 先分类在线/离线用户 for (DataSnapshot ds : snapshot.getChildren()) { User user = ds.getValue(User.class); if (user == null) continue; if (Boolean.TRUE.equals(ds.child("_online").getValue(Boolean.class))) { onlineUsers.add(user); } else { offlineUsers.add(user); } } // 第一步:移除离线用户的标记 for (User offlineUser : offlineUsers) { // 倒序遍历避免删元素时下标偏移漏删 for (int i = activeMarkers.size() - 1; i >= 0; i--) { Pair<String, Marker> pair = activeMarkers.get(i); if (pair.first.equals(offlineUser.get_uid())) { pair.second.remove(); activeMarkers.remove(i); break; } } } // 第二步:处理在线用户的标记,新增或更新位置 String currentUid = firebaseAuth.getCurrentUser().getUid(); for (User onlineUser : onlineUsers) { // 跳过当前用户自己,和无位置信息的用户 if (onlineUser.get_uid().equals(currentUid) || onlineUser.get_currentLocation() == null) { continue; } LatLng position = new LatLng(onlineUser.get_currentLocation().getLatitude(), onlineUser.get_currentLocation().getLongitude()); // 先查是否已有该用户的标记 boolean hasMarker = false; for (Pair<String, Marker> pair : activeMarkers) { if (pair.first.equals(onlineUser.get_uid())) { // 已有标记仅更新位置 pair.second.setPosition(position); hasMarker = true; break; } } // 没有标记就新建 if (!hasMarker) { MarkerOptions markerOptions = new MarkerOptions(); markerOptions.position(position); // 修复title为对应用户的昵称,而非当前用户 markerOptions.title(onlineUser.getDisplayName()); markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE)); Marker newMarker = mGoogleMap.addMarker(markerOptions); activeMarkers.add(new Pair<>(onlineUser.get_uid(), newMarker)); } } } @Override public void onCancelled(@NonNull DatabaseError error) { // 按需添加错误处理逻辑 } });
内容的提问来源于stack exchange,提问作者zivnadel
相关产品推荐
相关产品推荐

