ArrayList逻辑错误:符合条件的数据未正确存入列表(Firebase代码)
问题排查与修复方案
问题根源分析
- 列表被重复覆盖:在
geofenceDB的子节点循环中,每次迭代都给searchDB添加新的ValueEventListener,且每次onDataChange都会重新创建tutorArrayList。这导致最后一次循环的结果直接覆盖之前所有符合条件的数据——比如半径设为10时,最后遍历到距离290的节点,此时条件不满足,数组为空,最终显示空数组。 - 逻辑匹配倒置:当前代码错误地将
Geo-fence中每个用户的位置当作tutor的位置,再去Users中遍历所有用户判断类型。正确逻辑应该是:先从Users筛选出tutor类型的用户,再到Geo-fence获取该tutor的真实位置,计算与当前用户的距离是否在半径范围内。 - 资源浪费:重复添加监听会多次读取
searchDB数据,浪费带宽且引发不必要的UI刷新。
修正后的代码
searchDB = FirebaseDatabase.getInstance().getReference("Users"); geofenceDB = FirebaseDatabase.getInstance().getReference("Geo-fence"); searchList.setHasFixedSize(true); RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext()); searchList.setLayoutManager(layoutManager); String userID = FirebaseAuth.getInstance().getUid(); // 仅获取一次当前用户的位置与半径 geofenceDB.child(userID).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot userSnapshot) { if (!userSnapshot.exists()) return; final double userLat = userSnapshot.child("Latitude").getValue(Double.class); final double userLng = userSnapshot.child("Longitude").getValue(Double.class); final double userRadius = userSnapshot.child("Radius").getValue(Double.class); // 获取所有用户数据,筛选tutor类型 searchDB.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot usersSnapshot) { tutorArrayList = new ArrayList<>(); for (DataSnapshot userNode : usersSnapshot.getChildren()) { User tutor = userNode.getValue(User.class); if (tutor == null) continue; String typeData = tutor.getType().toLowerCase(Locale.ROOT); if (!"tutor".equals(typeData)) continue; // 获取当前tutor的位置数据 String tutorID = userNode.getKey(); geofenceDB.child(tutorID).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot tutorLocSnapshot) { if (!tutorLocSnapshot.exists()) return; double tutorLat = tutorLocSnapshot.child("Latitude").getValue(Double.class); double tutorLng = tutorLocSnapshot.child("Longitude").getValue(Double.class); // 判断距离是否符合要求,符合则加入列表 if (calculateDistanceInKilometer(userLat, userLng, tutorLat, tutorLng) <= userRadius) { tutorArrayList.add(tutor); } updateRecyclerView(); } @Override public void onCancelled(@NonNull DatabaseError error) {} }); } // 处理无符合条件数据的情况 updateRecyclerView(); } @Override public void onCancelled(@NonNull DatabaseError error) {} }); } @Override public void onCancelled(@NonNull DatabaseError error) {} }); // 统一UI更新逻辑,避免重复代码 private void updateRecyclerView() { if (adapter == null) { adapter = new SearchAdapter(getActivity(), tutorArrayList); searchList.setAdapter(adapter); } else { adapter.notifyDataSetChanged(); } if (tutorArrayList.isEmpty()) { searchList.setVisibility(View.GONE); empty.setVisibility(View.VISIBLE); } else { searchList.setVisibility(View.VISIBLE); empty.setVisibility(View.GONE); } }
关键优化点
- 使用
addListenerForSingleValueEvent替代addValueEventListener,避免持续监听数据变化,减少无效请求与UI刷新。 - 调整逻辑顺序:先筛选
tutor类型用户,再匹配其位置与距离条件,确保每个符合要求的tutor都能被正确加入列表。 - 提取独立的
updateRecyclerView方法,统一处理UI更新逻辑,避免代码冗余。 - 增加空值判断,防止因数据缺失引发的异常。
内容的提问来源于stack exchange,提问作者Izz
相关产品推荐
相关产品推荐

