You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio中如何在onBindViewHolder中应用条件并调整RecyclerView条目数

解决RecyclerView按距离过滤工人数据的正确实现

原代码核心问题

  • onBindViewHolder中使用do-while循环遍历整个数据集是错误的:该方法是每个item绑定视图时调用,每次调用都遍历会导致重复计算、索引混乱,甚至引发崩溃。
  • 绑定过程中直接修改数据源(remove元素)并调用notifyItemRemoved,会破坏RecyclerView的回收机制,导致视图展示异常。
  • count变量维护逻辑混乱,无法准确反映实际需要展示的item数量。
  • 直接引用静态类的坐标变量,耦合性过高,不利于代码维护。

正确实现方案

1. 封装Haversine距离计算工具方法

把距离计算逻辑抽成独立方法,提升复用性和代码可读性:

public class DistanceCalculator {
    private static final double EARTH_RADIUS_KM = 6371;

    public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        double dLat = Math.toRadians(lat2 - lat1);
        double dLon = Math.toRadians(lon2 - lon1);

        lat1 = Math.toRadians(lat1);
        lat2 = Math.toRadians(lat2);

        double a = Math.pow(Math.sin(dLat / 2), 2) +
                Math.pow(Math.sin(dLon / 2), 2) * Math.cos(lat1) * Math.cos(lat2);
        double c = 2 * Math.asin(Math.sqrt(a));

        return EARTH_RADIUS_KM * c;
    }
}

2. 修正后的RecyclerView Adapter

Adapter只负责展示过滤后的数据,过滤逻辑提前完成:

public class WorkerAdapter extends RecyclerView.Adapter<WorkerAdapter.WorkerViewHolder> {

    private Context context;
    private ArrayList<user_data> filteredWorkerList;

    // 构造方法:传入上下文、原始工人列表和客户端坐标,直接完成数据过滤
    public WorkerAdapter(Context context, ArrayList<user_data> originalWorkerList, double clientLat, double clientLon) {
        this.context = context;
        this.filteredWorkerList = filterWorkersByDistance(originalWorkerList, clientLat, clientLon);
    }

    // 过滤符合距离条件的工人
    private ArrayList<user_data> filterWorkersByDistance(ArrayList<user_data> originalList, double clientLat, double clientLon) {
        ArrayList<user_data> filteredList = new ArrayList<>();
        for (user_data worker : originalList) {
            double workerLat = worker.getWorker_lattitude();
            double workerLon = worker.getWorker_longitude();
            double workingRadius = worker.getWork_Km();

            // 计算工人与客户端的距离
            double distance = DistanceCalculator.calculateDistance(workerLat, workerLon, clientLat, clientLon);

            // 距离小于等于工作半径则保留
            if (distance <= workingRadius) {
                filteredList.add(worker);
            }
        }
        return filteredList;
    }

    @NonNull
    @Override
    public WorkerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.single_row, parent, false);
        return new WorkerViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull WorkerViewHolder holder, int position) {
        // 直接绑定过滤后的数据,无需额外判断
        user_data worker = filteredWorkerList.get(position);
        holder.w_name.setText(worker.getWorker_Name());
        holder.w_desc.setText(worker.getWorker_description());
    }

    @Override
    public int getItemCount() {
        // 直接返回过滤后列表的大小,无需维护额外count变量
        return filteredWorkerList.size();
    }

    public static class WorkerViewHolder extends RecyclerView.ViewHolder {
        TextView w_name, w_desc;

        public WorkerViewHolder(@NonNull View itemView) {
            super(itemView);
            w_name = itemView.findViewById(R.id.worker_name);
            w_desc = itemView.findViewById(R.id.worker_desc);
        }
    }

    // 可选:客户端坐标更新时,重新过滤数据并刷新列表
    public void updateClientLocation(double newClientLat, double newClientLon, ArrayList<user_data> originalWorkerList) {
        this.filteredWorkerList = filterWorkersByDistance(originalWorkerList, newClientLat, newClientLon);
        notifyDataSetChanged();
    }
}

3. 使用示例

在Activity/Fragment中获取客户端坐标和Firestore工人数据后,初始化Adapter:

// 假设已获取客户端经纬度clientLat、clientLon,以及Firestore返回的workerList
WorkerAdapter adapter = new WorkerAdapter(this, workerList, clientLat, clientLon);
recyclerView.setAdapter(adapter);

内容的提问来源于stack exchange,提问作者dinesh dine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 01:57:38