Android开发:如何将Firebase获取的营地数据按用户与营地距离由近到远排序并在RecyclerView展示
如何按距离排序营地数据并在RecyclerView展示
嘿,你已经搞定了最核心的距离计算部分,接下来实现排序其实非常简单,咱们一步步来:
1. 确认数据模型支持排序
首先确保你的CamperSiteModel类已经正确实现了distance字段的getter和setter方法(从你的代码看已经在调用setDistance,这步应该没问题),并且这个字段是可比较的数值类型(比如Integer或者Double)。
2. 在获取完数据后添加排序逻辑
你现在是把计算完距离的营地直接加入列表,只需要在通知Adapter更新之前,对camperSiteModel列表做一次排序即可。Java里可以用Collections.sort()配合自定义的Comparator来实现按距离由近到远排序。
3. 修改后的完整代码示例
我把排序逻辑加到你的代码里,同时修正了一个可能的小bug(经度没有转弧度,会导致距离计算不准确):
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Campsite"); Query query = reference.orderByChild("country").equalTo(country); query.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { progressDialog.dismiss(); if(seatch_bar.getText().toString().equals("")){ camperSiteModel.clear(); for(DataSnapshot snapshot : dataSnapshot.getChildren()){ CamperSiteModel camperSiteModel1 = snapshot.getValue(CamperSiteModel.class); double radLat1 = rad(camperSiteModel1.getCamperSiteLatitude()); double radLat2 = rad(latitude); double a = radLat1 - radLat2; // 修正:经度也要转成弧度后再计算差值 double b = rad(camperSiteModel1.getCamperSiteLongitude()) - rad(longitude); double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2))); s = s * EARTH_RADIUS; s = Math.round(s * 10000) / 10000; Log.i("Distance",Math.ceil(s)+""); camperSiteModel1.setDistance(Math.ceil(s)); camperSiteModel.add(camperSiteModel1); } // 新增:按距离由近到远排序 Collections.sort(camperSiteModel, new Comparator<CamperSiteModel>() { @Override public int compare(CamperSiteModel o1, CamperSiteModel o2) { // 这里用Integer.compare是因为你用了Math.ceil转成整数 // 如果distance是Double类型,就换成Double.compare(o1.getDistance(), o2.getDistance()) return Integer.compare(o1.getDistance(), o2.getDistance()); } }); camperSiteAdapter.notifyDataSetChanged(); } } @Override public void onCancelled(@NonNull DatabaseError databaseError) { // 别忘了处理请求取消的情况,避免进度框一直显示 progressDialog.dismiss(); Log.e("Firebase Error", databaseError.getMessage()); } });
4. 几个注意点
- 主线程操作:Firebase Realtime Database的监听回调默认在主线程执行,所以这里直接排序和更新Adapter是安全的,如果是在子线程计算距离,记得切换回主线程再做这些操作。
- 空列表判断:如果查询结果为空,排序操作不会报错,但可以加个
if (!camperSiteModel.isEmpty())的判断,让逻辑更严谨。
内容的提问来源于stack exchange,提问作者user16489264
相关产品推荐
相关产品推荐

