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
相关产品推荐
相关产品推荐

