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

RecyclerView加载Room数据库数据首次显示重复问题求助

问题分析与解决方案

核心问题原因

首次进入Fragment时列表重复,大概率是数据加载逻辑重复执行,或者Adapter初始化/数据更新方式存在冗余,导致productList被重复填充数据;点击按钮后重新加载数据恢复正常,说明Room查询本身返回的是正确数据,问题出在数据填充或Adapter的初始化流程上。

具体修复步骤

1. 排查Fragment的数据加载逻辑

确保在Fragment生命周期中仅执行一次数据初始化,比如在onViewCreated中完成,避免在onResume或其他重复触发的生命周期方法中重复添加数据:

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    // 初始化列表和Adapter,仅执行一次
    List<Product> productList = new ArrayList<>();
    productList.addAll(BroojDB.getInstance(getContext()).productDao().getAllProduct());
    CartAdapter adapter = new CartAdapter(getContext(), productList);
    recyclerView.setAdapter(adapter);
}

2. 优化CartAdapter代码

移除冗余操作,提升性能同时避免数据异常:

private Context context;
private List<Product> productList;
private BroojDB database;

// 构造方法中初始化数据库实例,避免重复获取
public CartAdapter(Context context, List<Product> productList) {
    this.context = context;
    this.productList = productList;
    this.database = BroojDB.getInstance(context);
    // 移除不必要的notifyDataSetChanged(),此时Adapter尚未绑定RecyclerView
}

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

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
    Product product = productList.get(position);
    int count = product.getCount();
    float productPrice = product.getPrice();
    float subTotal = count * productPrice;

    holder.count.setText(String.valueOf(count));
    holder.title.setText(product.getTitle());
    holder.price.setText(String.format("%f SD", productPrice));
    holder.subTotal.setText(String.format("%f SD", subTotal));
    holder.deleteProductFromCart.setBackgroundResource(R.drawable.cancel);

    holder.increaseOne.setOnClickListener(v -> {
        int adapterPosition = holder.getAdapterPosition();
        if (adapterPosition == RecyclerView.NO_POSITION) return;

        Product p = productList.get(adapterPosition);
        int newCount = p.getCount() + 1;
        // 更新数据库
        database.productDao().updateProduct(p.getId(), p.getTitle(), p.getPrice(), newCount);
        // 直接修改列表对象,无需清空重加载
        p.setCount(newCount);
        // 仅更新当前项,提升性能
        notifyItemChanged(adapterPosition);
    });

    holder.decreaseOne.setOnClickListener(v -> {
        int adapterPosition = holder.getAdapterPosition();
        if (adapterPosition == RecyclerView.NO_POSITION) return;

        Product p = productList.get(adapterPosition);
        int currentCount = p.getCount();
        if (currentCount <= 1) return;

        int newCount = currentCount - 1;
        database.productDao().updateProduct(p.getId(), p.getTitle(), p.getPrice(), newCount);
        p.setCount(newCount);
        notifyItemChanged(adapterPosition);
    });

    holder.deleteProductFromCart.setOnClickListener(v -> {
        int adapterPosition = holder.getAdapterPosition();
        if (adapterPosition == RecyclerView.NO_POSITION) return;

        Product p = productList.get(adapterPosition);
        database.productDao().deleteProduct(p);
        productList.remove(adapterPosition);
        notifyItemRemoved(adapterPosition);
        notifyItemRangeChanged(adapterPosition, productList.size());
    });
}

@Override
public int getItemCount() {
    return productList.size();
}

public class MyViewHolder extends RecyclerView.ViewHolder {
    Button increaseOne, decreaseOne, deleteProductFromCart;
    TextView title, price, subTotal, count;

    public MyViewHolder(@NonNull View itemView) {
        super(itemView);
        increaseOne = itemView.findViewById(R.id.increase_product_one);
        decreaseOne = itemView.findViewById(R.id.decrease_one);
        deleteProductFromCart = itemView.findViewById(R.id.remove_item);
        title = itemView.findViewById(R.id.item_title);
        price = itemView.findViewById(R.id.item_price);
        subTotal = itemView.findViewById(R.id.sub_total);
        count = itemView.findViewById(R.id.count_off_product_in_cart);
    }
}

关键优化点

  • 移除构造方法中无效的notifyDataSetChanged()调用;
  • 在构造中初始化database实例,避免onBindViewHolder中重复获取;
  • 更新数量时直接修改列表中的Product对象,调用notifyItemChanged()局部刷新,替代清空列表重加载的低效方式;
  • 添加adapterPosition == RecyclerView.NO_POSITION的判断,避免ViewHolder复用导致的空指针。

内容的提问来源于stack exchange,提问作者Elfadil Sulieman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 16:05:24