RecyclerView数据变更通知异常:删图后拍照仍显示旧内容问题
Android文件管理器RecyclerView显示旧图问题排查与解决
我开发了一款带相机功能的文件管理器应用,拍照后图片能正常在RecyclerView中显示,但删除任意图片后再次拍照,RecyclerView仍显示旧图片,实际存储路径下已经是新图片。尝试过调用notifyDataSetChanged()、notifyItemRemoved()方法,也执行过RefreshData()重新获取路径数据,但都无效。以下是相关代码及已尝试的操作注释:
适配器类
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{ Context context; ArrayList<File> filesAndFolders; RecycleAction recycleAction; public MyAdapter(Context context, ArrayList<File> filesAndFolders,RecycleAction recycleAction){ this.context = context; this.filesAndFolders = filesAndFolders; this.recycleAction = recycleAction; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(context).inflate(R.layout.recycle_gird_item,parent,false); return new ViewHolder(view,recycleAction); } @Override public void onBindViewHolder(ViewHolder holder, int position) { File selectedFile = filesAndFolders.get(position); holder.textView.setText(selectedFile.getName()); holder.imageView.setImageResource(R.drawable.ic_baseline_folder_24); ImageFileFilter img = new ImageFileFilter(); if (img.accept(selectedFile)) { new Thread(new Runnable() { @Override public void run() { ((AppCompatActivity) context ).runOnUiThread(new Runnable() { @Override public void run() { Glide.with(context.getApplicationContext()).load(selectedFile).placeholder(R.drawable.border).into(holder.imageView); } }); } }).start(); } else { if (selectedFile.isDirectory()) { holder.imageView.setImageResource(R.drawable.ic_baseline_folder_24); } else { // 非图片文件 holder.imageView.setImageResource(R.drawable.ic_baseline_insert_drive_file_24); } } } @Override public int getItemCount() { return filesAndFolders.size(); } public class ViewHolder extends RecyclerView.ViewHolder{ TextView textView; ImageView imageView; public ViewHolder(View itemView,RecycleAction recycleAction) { super(itemView); textView = itemView.findViewById(R.id.file_name_gird); imageView = itemView.findViewById(R.id.icon_view_gird); itemView.setOnClickListener(v->{ recycleAction.onClick(itemView,getAdapterPosition()); }); itemView.setOnLongClickListener(v->{ recycleAction.onLongClick(itemView , getAdapterPosition()); return true; }); } } }
长按点击事件
@Override public void onLongClick(View item,int position) { File selectedFile = filesAndFolders.get(position); ImageView img = item.findViewById(R.id.icon_view_gird); PopupMenu popupMenu = new PopupMenu(MainActivity.this,item); popupMenu.getMenu().add("DELETE"); popupMenu.getMenu().add("SHARE"); popupMenu.getMenu().add("RENAME"); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { // 问题出在这里 if(item.getTitle().equals("DELETE")){ Toast.makeText(MainActivity.this,"DELETED ",Toast.LENGTH_SHORT).show(); item.setVisible(false); selectedFile.delete(); adapter.notifyItemRemoved(position); // RefreshData(path,filesAndFolders); // adapter.notifyDataSetChanged(); //adapter.notifyItemChanged(position); // 试过上述方法,最后只能重启Activity解决 startActivity(getIntent().addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)); } if(item.getTitle().equals("SHARE")){ BitmapDrawable bitmapDrawable=(BitmapDrawable) img.getDrawable(); Bitmap bit = bitmapDrawable.getBitmap(); shareImageandText(bit,selectedFile); } if(item.getTitle().equals("RENAME")){ Toast.makeText(MainActivity.this,"RENAME ",Toast.LENGTH_SHORT).show(); } return true; } }); popupMenu.show(); }
RefreshData方法
private void RefreshData(String path, ArrayList<File> filesAndFolders){ filesAndFolders.clear(); if(path==null){ File root = new File(DIRICTORY); ArrayList<File> diractorus = new ArrayList<>(Arrays.asList(root.listFiles())); ArrayList<File> diractorus_new = new ArrayList<>(); ArrayList<File> imagesss =new ArrayList<>(); for (File item:diractorus) { if (item.isDirectory()) { diractorus_new.add(item); }else{ imagesss.add(item); } } Collections.sort(imagesss); Collections.sort(diractorus_new); diractorus_new.addAll(imagesss); filesAndFolders.addAll(diractorus_new); }else { File root = new File(path); ArrayList<File> diractorus = new ArrayList<>(Arrays.asList(root.listFiles())); ArrayList<File> diractorus_new = new ArrayList<>(); ArrayList<File> imagesss =new ArrayList<>(); for (File item:diractorus) { if (item.isDirectory()) { diractorus_new.add(item); }else{ imagesss.add(item); } } filesAndFolders.addAll(diractorus_new); filesAndFolders.addAll(imagesss); } adapter.notifyDataSetChanged(); }
问题原因与解决方案
核心问题1:删除操作未同步数据源
执行selectedFile.delete()后,只调用了adapter.notifyItemRemoved(position),但没有从绑定的filesAndFolders列表中移除对应的File对象。这会导致数据源和RecyclerView的视图状态不一致,后续刷新时旧的File对象仍存在于列表中,Glide会继续加载缓存的旧图。
修复删除逻辑:
if(item.getTitle().equals("DELETE")){ Toast.makeText(MainActivity.this,"DELETED ",Toast.LENGTH_SHORT).show(); selectedFile.delete(); // 先从数据源移除元素 filesAndFolders.remove(position); // 再通知适配器更新 adapter.notifyItemRemoved(position); // 通知后续元素位置变化 adapter.notifyItemRangeChanged(position, filesAndFolders.size() - position); // 调用RefreshData刷新最新列表 RefreshData(path, filesAndFolders); }
核心问题2:Glide缓存导致旧图残留
删除图片后重新拍照,若生成的新图片与旧图片文件名相同,Glide会默认使用磁盘缓存的旧图,不会重新读取新文件。
修复Glide加载逻辑:
在加载图片时添加文件签名,基于文件的修改时间或长度,确保文件变化时Glide重新加载:
// 替换适配器中Glide加载的代码 Glide.with(context.getApplicationContext()) .load(selectedFile) .placeholder(R.drawable.border) // 添加签名,用文件最后修改时间作为标识 .signature(new ObjectKey(selectedFile.lastModified())) .into(holder.imageView);
优化RefreshData方法
确保重新加载时获取最新的文件列表,避免依赖缓存的File对象,同时统一排序逻辑:
private void RefreshData(String path, ArrayList<File> filesAndFolders){ filesAndFolders.clear(); File root; if(path == null){ root = new File(DIRICTORY); } else { root = new File(path); } // 先判断目录是否存在且可读取 if(!root.exists() || !root.canRead()){ adapter.notifyDataSetChanged(); return; } File[] fileArray = root.listFiles(); if(fileArray == null){ adapter.notifyDataSetChanged(); return; } ArrayList<File> directories = new ArrayList<>(); ArrayList<File> images = new ArrayList<>(); ImageFileFilter imgFilter = new ImageFileFilter(); for (File item : fileArray) { if (item.isDirectory()) { directories.add(item); } else if(imgFilter.accept(item)){ images.add(item); } } // 统一排序 Collections.sort(directories); Collections.sort(images); directories.addAll(images); filesAndFolders.addAll(directories); adapter.notifyDataSetChanged(); }
内容的提问来源于stack exchange,提问作者Djamel Tayeb
相关产品推荐
相关产品推荐

