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

Firestore调用数据两次致RecyclerView条目重复问题求助

RecyclerView加载Firestore数据出现重复条目的解决方案

问题原因

你的代码中productList.clear()仅在调用loadData()时执行一次,但addSnapshotListener是实时监听,会在初始加载数据、后续Firestore数据发生变更时多次触发onEvent方法。每次触发时,你都会将ADDED类型的数据添加到列表中,却没有在每次处理数据前清空列表,导致旧数据未被清除,新数据不断追加,最终出现条目重复。

修改后的代码

private void loadData() {
    firestore.collection("Products").orderBy("order")
            .addSnapshotListener(new EventListener<QuerySnapshot>() {
                @SuppressLint("NotifyDataSetChanged")
                @Override
                public void onEvent(@Nullable QuerySnapshot value, @Nullable FirebaseFirestoreException error) {
                    // 处理错误情况
                    if(error != null) {
                        if(progressDialog.isShowing()){
                            progressDialog.dismiss();
                            Log.e("Firestore gives server error", error.getMessage());
                            new Flashbar.Builder(requireActivity())
                                    .gravity(Flashbar.Gravity.BOTTOM)
                                    .duration(500)
                                    .backgroundColorRes(com.margsapp.iosdialog.R.color.red)
                                    .messageColorRes(R.color.white)
                                    .showOverlay()
                                    .showIcon()
                                    .message("Something went wrong please try again later.")
                                    .build();
                        }
                        return; // 出错后终止后续逻辑
                    }

                    // 空值判断,避免崩溃
                    if (value == null) {
                        if(progressDialog.isShowing()){
                            progressDialog.dismiss();
                        }
                        return;
                    }

                    // 每次处理数据前清空列表,避免重复
                    productList.clear();

                    // 遍历所有文档变更,处理不同类型的操作
                    for (DocumentChange documentChange : value.getDocumentChanges()){
                        Product product = documentChange.getDocument().toObject(Product.class);
                        switch (documentChange.getType()) {
                            case ADDED:
                                productList.add(product);
                                break;
                            case MODIFIED:
                                // 找到对应条目并更新
                                int updateIndex = findProductIndex(product);
                                if (updateIndex != -1) {
                                    productList.set(updateIndex, product);
                                }
                                break;
                            case REMOVED:
                                // 找到对应条目并删除
                                int removeIndex = findProductIndex(product);
                                if (removeIndex != -1) {
                                    productList.remove(removeIndex);
                                }
                                break;
                        }
                    }

                    productAdapter.notifyDataSetChanged();
                    if(progressDialog.isShowing()){
                        progressDialog.dismiss();
                    }
                }
            });
}

// 辅助方法:根据产品唯一标识查找列表中的位置(需替换为你的Product类实际唯一字段,比如id)
private int findProductIndex(Product product) {
    for (int i = 0; i < productList.size(); i++) {
        if (productList.get(i).getId().equals(product.getId())) {
            return i;
        }
    }
    return -1;
}

关键修改点说明

  • 将productList.clear()移至onEvent方法内部,确保每次监听触发时先清空旧数据,再加载最新数据。
  • 新增对MODIFIED和REMOVED类型文档变更的处理,保证RecyclerView能同步响应Firestore的数据更新和删除操作。
  • 增加value == null的判断,替代原有的assert,避免空指针崩溃。
  • 错误处理后添加return,防止后续代码继续执行引发异常。

内容的提问来源于stack exchange,提问作者Mohammed Abid Nafi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 18:31:05