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

如何从Glide加载的RecyclerView中移除点击的图片

解决RecyclerView移除Glide加载图片后出现重复项的问题

问题描述

我查了大量资料,想找到从Glide加载图片的RecyclerView里移除点击图片的方法,但没找到相关内容。能看到的示例基本都围绕Glide的diskCacheStrategy这类缓存策略展开,没人讲怎么从RecyclerView中移除图片。

我的需求是移除列表中被点击的图片,当前填充RecyclerView的代码:

@Override
public void onBindViewHolder(@NonNull ImageGalleryAdapter.MyViewHolder holder, int position) {
    fbPhotos fbPhotos = mFbPhotos[position];
    ImageView imageView = holder.mPhotoImageView;

    Glide.with(mContext)
        .load(fbPhotos.getUrl())
        .placeholder(R.drawable.ic_cloud_off_red)
        .into(imageView);
}

检测图片点击的代码:

public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    public ImageView mPhotoImageView;

    public MyViewHolder(View itemView) {
        super(itemView);
        mPhotoImageView = itemView.findViewById(R.id.iv_photo);
        itemView.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        int position = getAdapterPosition();

        if(position != RecyclerView.NO_POSITION) {
            fbPhotos fbPhotos = mFbPhotos[position];
        }
    }
}

完整代码:

public class frag_photos extends Fragment {
    public frag_photos() {
        // Required empty public constructor
    }

    private fbPhotos[] mFbPhotos;
    private Context mContext;
    SwipeRefreshLayout swipeLayout;
    RecyclerView recyclerView;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.frag_photos, container, false);

        RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getContext(), 2);
        recyclerView = view.findViewById(R.id.rv_images);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(layoutManager);

        ImageGalleryAdapter adapter = new ImageGalleryAdapter(getContext(), fbPhotos.getFBPhotos());
        recyclerView.setAdapter(adapter);

        //Getting SwipeContainerLayout
        swipeLayout = view.findViewById(R.id.swipe_container);

        //swip listener
        swipeLayout.setOnRefreshListener(() -> {
            Log.d("test", "regresh");
            swipeLayout.setRefreshing(false);
        });

        return view;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    private class ImageGalleryAdapter extends RecyclerView.Adapter<ImageGalleryAdapter.MyViewHolder>  {
        @NonNull
        @Override
        public ImageGalleryAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            Context context = parent.getContext();
            LayoutInflater inflater = LayoutInflater.from(context);
            View photoView = inflater.inflate(R.layout.item_photo, parent, false);
            ImageGalleryAdapter.MyViewHolder viewHolder = new ImageGalleryAdapter.MyViewHolder(photoView);

            return viewHolder;
        }

        @Override
        public void onBindViewHolder(@NonNull ImageGalleryAdapter.MyViewHolder holder, int position) {
            fbPhotos fbPhotos = mFbPhotos[position];
            ImageView imageView = holder.mPhotoImageView;

            Glide.with(mContext)
                .load(fbPhotos.getUrl())
                .placeholder(R.drawable.ic_cloud_off_red)
                .into(imageView);
        }

        @Override
        public int getItemCount() {
            return (mFbPhotos.length);
        }

        public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
            public ImageView mPhotoImageView;

            public MyViewHolder(View itemView) {
                super(itemView);

                mPhotoImageView = itemView.findViewById(R.id.iv_photo);
                itemView.setOnClickListener(this);
            }

            @Override
            public void onClick(View view) {
                int position = getAdapterPosition();

                if(position != RecyclerView.NO_POSITION) {
                    fbPhotos fbPhotos = mFbPhotos[position];
                }
            }
        }

        public ImageGalleryAdapter(Context context, List<fbPhotos> fbPhotos) {
            mContext = context;
            mFbPhotos = fbPhotos.toArray(new fbPhotos[0]);
        }
    }
}

我尝试用notifyItemRemoved(position)方法移除图片,虽然能删掉点击的项,但每次点击都会在列表里添加最后一张图片的副本(表现为删除一项后,最后一项重复出现)。

问题根源

你当前用固定长度的数组存储数据,调用notifyItemRemoved(position)时,RecyclerView的视图会更新,但数组里的数据并没有真正删除对应元素,再加上RecyclerView的视图复用机制,就会导致最后一项被重复绑定显示。

解决步骤

1. 替换数据存储类型

把原来的fbPhotos[]数组换成List<fbPhotos>,List支持动态添加/删除元素,能保证数据和视图同步。

2. 修改适配器代码

  • 让适配器直接持有List引用,不用转成数组
  • 在点击事件中先删除List中的对应元素,再通知适配器更新
  • 绑定视图前清空ImageView,避免复用显示旧图片

修改后的完整代码示例

Fragment部分修改

public class frag_photos extends Fragment {
    public frag_photos() {
        // Required empty public constructor
    }

    // 把数组换成List
    private List<fbPhotos> mFbPhotos;
    private Context mContext;
    SwipeRefreshLayout swipeLayout;
    RecyclerView recyclerView;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.frag_photos, container, false);

        RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getContext(), 2);
        recyclerView = view.findViewById(R.id.rv_images);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(layoutManager);

        ImageGalleryAdapter adapter = new ImageGalleryAdapter(getContext(), fbPhotos.getFBPhotos());
        recyclerView.setAdapter(adapter);

        swipeLayout = view.findViewById(R.id.swipe_container);
        swipeLayout.setOnRefreshListener(() -> {
            Log.d("test", "regresh");
            swipeLayout.setRefreshing(false);
        });

        return view;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    // 修改后的适配器
    private class ImageGalleryAdapter extends RecyclerView.Adapter<ImageGalleryAdapter.MyViewHolder>  {
        private List<fbPhotos> mFbPhotos;
        private Context mContext;

        @NonNull
        @Override
        public ImageGalleryAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            Context context = parent.getContext();
            LayoutInflater inflater = LayoutInflater.from(context);
            View photoView = inflater.inflate(R.layout.item_photo, parent, false);
            return new MyViewHolder(photoView);
        }

        @Override
        public void onBindViewHolder(@NonNull ImageGalleryAdapter.MyViewHolder holder, int position) {
            fbPhotos photo = mFbPhotos.get(position);
            ImageView imageView = holder.mPhotoImageView;

            // 绑定新数据前清空旧图片,避免复用错误
            Glide.with(mContext).clear(imageView);
            
            Glide.with(mContext)
                .load(photo.getUrl())
                .placeholder(R.drawable.ic_cloud_off_red)
                .into(imageView);
        }

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

        public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
            public ImageView mPhotoImageView;

            public MyViewHolder(View itemView) {
                super(itemView);
                mPhotoImageView = itemView.findViewById(R.id.iv_photo);
                itemView.setOnClickListener(this);
            }

            @Override
            public void onClick(View view) {
                int position = getAdapterPosition();
                if(position != RecyclerView.NO_POSITION) {
                    // 1. 真正删除数据集合中的元素
                    mFbPhotos.remove(position);
                    // 2. 通知适配器移除对应位置的视图
                    notifyItemRemoved(position);
                    // 可选:通知后续项索引变化,防止绑定错误
                    notifyItemRangeChanged(position, mFbPhotos.size());
                }
            }
        }

        // 构造方法直接接收List
        public ImageGalleryAdapter(Context context, List<fbPhotos> fbPhotos) {
            mContext = context;
            mFbPhotos = fbPhotos;
        }
    }
}

关键说明

  • 必须先修改数据集合,再调用notifyItemRemoved,否则视图和数据不同步会导致复用错误
  • 用Glide.with(mContext).clear(imageView)可以避免复用的ViewHolder显示之前加载的图片,这在列表项删除、排序场景中很重要

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 19:25:31