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

RecyclerView中CardView按钮事件错位:点击首项触发末项问题修复

问题解决:RecyclerView按钮点击触发错误Item数据操作

问题原因

  1. 全局变量被复用覆盖:Adapter中定义的idVolunteer、idOrganization、documentPendingID是类成员变量,RecyclerView的ViewHolder会被复用,每次执行onBindViewHolder都会更新这些变量的值,导致点击按钮时,变量存储的是最后一次绑定的Item数据,而非当前点击的Item数据。
  2. 异步查询的时序问题:onBindViewHolder中发起的Firestore查询是异步执行的,当查询完成时,当前ViewHolder可能已经被复用给其他Item,documentPendingID会被后续绑定的Item修改,最终删除的是最后一条查询到的文档。
  3. 查询条件不准确:使用whereEqualTo("organizationId", idOrganization)会查询该组织下所有的待处理请求,而非当前Item对应的单条请求,循环赋值后documentPendingID只会保留最后一条查询结果的ID。

解决方案

  1. 移除全局变量,使用局部变量或当前Item的快照ID:利用FirestoreRecyclerAdapter的getSnapshots().getSnapshot(position).getId()直接获取当前Item对应的Firestore文档ID,无需额外查询。
  2. 直接使用当前Item的Request对象数据:在onBindViewHolder中,直接从传入的request对象中获取所需的volunteerId和organizationId,避免依赖全局变量。
  3. 简化Firestore操作逻辑:不需要通过查询获取文档ID,直接用当前Item的快照ID执行删除操作。

修正后的代码

public class RequestAdapter extends FirestoreRecyclerAdapter<Request, RequestAdapter.ViewHolder> {
    private ArrayList<Volunteer> mVolunteer = new ArrayList<>();
    FirebaseFirestore mFirestore = FirebaseFirestore.getInstance();

    public RequestAdapter(@NonNull FirestoreRecyclerOptions<Request> options){
        super(options);
    }

    @Override
    protected void onBindViewHolder(@NonNull ViewHolder holder, int position, @NonNull Request request) {
        holder.txtNameSurname.setText(request.getFullName());
        holder.txtStatusRequest.setText("Solicitud pendiente de aceptación");
        holder.txtDateRequest.setText(request.getDate());
        
        // 获取当前Item对应的Firestore文档ID
        final String pendingDocId = getSnapshots().getSnapshot(position).getId();
        final String volunteerId = request.getVolunteerId();
        final String organizationId = request.getOrganizationId();

        holder.btnOk.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 更新组织的志愿者列表
                DocumentReference volunteerRef = mFirestore.collection("organizations").document(organizationId);
                volunteerRef.update("volunteers", FieldValue.arrayUnion(volunteerId));
                
                // 更新志愿者的组织ID
                DocumentReference organizationsRef = mFirestore.collection("volunteers").document(volunteerId);
                organizationsRef.update("organizationId", organizationId);

                // 删除当前待处理请求文档
                mFirestore.collection("pendingVolunteerRequests").document(pendingDocId)
                        .delete()
                        .addOnSuccessListener(new OnSuccessListener<Void>() {
                            @Override
                            public void onSuccess(Void aVoid) {
                                // 可添加成功后的提示逻辑
                            }
                        })
                        .addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                // 可添加失败后的提示逻辑
                            }
                        });
            }
        });

        holder.btnNoOk.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 直接删除当前待处理请求文档,无需查询
                mFirestore.collection("pendingVolunteerRequests").document(pendingDocId)
                        .delete()
                        .addOnSuccessListener(new OnSuccessListener<Void>() {
                            @Override
                            public void onSuccess(Void aVoid) {
                                // 可添加成功后的提示逻辑
                            }
                        })
                        .addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                // 可添加失败后的提示逻辑
                            }
                        });
            }
        });
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.pending_request, viewGroup, false);
        return new ViewHolder(view);
    }

    public class ViewHolder extends RecyclerView.ViewHolder{
        TextView txtNameSurname;
        TextView txtDateRequest;
        TextView txtStatusRequest;
        Button btnOk;
        Button btnNoOk;

        public ViewHolder(@NonNull View itemView){
            super(itemView);
            txtNameSurname = itemView.findViewById(R.id.txtNameSurname);
            txtDateRequest = itemView.findViewById(R.id.txtDate);
            txtStatusRequest = itemView.findViewById(R.id.txtStatus);
            btnOk = itemView.findViewById(R.id.btnAccept);
            btnNoOk = itemView.findViewById(R.id.btnDecline);
        }
    }
}

关键说明

  • 利用getSnapshots().getSnapshot(position).getId()直接获取当前Item对应的Firestore文档ID,避免了异步查询带来的时序问题和数据覆盖问题。
  • 将volunteerId、organizationId、pendingDocId定义为onBindViewHolder内的局部变量,确保每个Item的点击事件使用的是自身对应的数据。
  • 简化了Reject按钮的逻辑,直接删除当前Item对应的文档,无需再次查询,提升了效率并避免误删其他请求。

内容的提问来源于stack exchange,提问作者Joaquin Poggio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 23:25:33