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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 22:27:33