Android RecyclerView加载Firebase Realtime数据库图片重复显示问题
问题根因
- 数据列表未清空:Firebase的
ValueEventListener的onDataChange回调会触发多次,首次返回本地缓存数据,后续返回云端同步的最新数据,你每次回调时都直接向全局的imagesFromURL列表追加数据,没有清空之前加载的旧数据,所以第一次加载加了5张,第二次又加了相同的5张,最终列表长度就是10张,出现重复。 - 重复初始化RecyclerView:你每次
onDataChange触发时都调用initRecyclerView重新设置适配器,属于不必要的重复操作,也会增加异常概率。 - 补充:你给出的代码中还遗漏了给数据库引用绑定监听器的步骤,会导致数据无法正常加载。
修复方案
步骤1:调整RecyclerView初始化时机
把RecyclerView的初始化逻辑放到onCreate中执行,全程只初始化一次,后续数据更新时只刷新适配器即可。
步骤2:优化onDataChange数据加载逻辑
每次加载新数据前先清空旧列表,避免重复追加。
修改后的Activity代码:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityWorkDetailsBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); workUid_details = getIntent().getExtras().getString("UID_Details"); String title = getIntent().getExtras().getString("name"); String description = getIntent().getExtras().getString("description"); String location = getIntent().getExtras().getString("location"); String path = getIntent().getExtras().getString("path"); // 提前初始化RecyclerView,仅执行一次 initRecyclerView(); databaseReference = FirebaseDatabase.getInstance().getReference().child("Work").child(path); valueEventListener = new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { binding.workDetailsTitle.setText(title); binding.workDetailsDescription.setText(description); binding.workDetailsLocation.setText(location); binding.getUIDDetails.setText(workUid_details); // 关键:加载新数据前先清空旧列表 imagesFromURL.clear(); for (DataSnapshot dataSnapshot : snapshot.child("images").getChildren()) { String value = String.valueOf(dataSnapshot.child("image").getValue()); imagesFromURL.add(value); } // 仅通知适配器数据更新,不用重新初始化RecyclerView binding.workDetailsImage.getAdapter().notifyDataSetChanged(); binding.progressBar.setVisibility(View.GONE); } @Override public void onCancelled(@NonNull DatabaseError error) { } }; // 绑定监听器,原代码遗漏了这步 databaseReference.addValueEventListener(valueEventListener); } private void initRecyclerView(){ binding.workDetailsImage.setNestedScrollingEnabled(false); binding.workDetailsImage.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); binding.workDetailsImage.setHasFixedSize(true); WorkDetailsAdapter adapter = new WorkDetailsAdapter(this, imagesFromURL); binding.workDetailsImage.setAdapter(adapter); binding.progressBar.setVisibility(View.VISIBLE); }
可选优化
为了降低代码耦合,你可以在适配器中新增数据更新方法,避免直接操作全局列表:
// 在WorkDetailsAdapter中添加此方法 public void updateData(List<String> newImageList) { mImages.clear(); mImages.addAll(newImageList); notifyDataSetChanged(); }
之后在onDataChange中直接调用adapter.updateData(imagesFromURL)刷新即可。
内容的提问来源于stack exchange,提问作者MiniDev99
相关产品推荐
相关产品推荐

