Glide 3.8.0在RecyclerView快速滚动时出现图片重复问题求助
我之前也碰到过一模一样的问题——快速滚动RecyclerView时,总有几个item会显示重复的图片,慢滚就完全正常。结合你贴的代码来看,问题主要出在Glide的Target绑定和ViewHolder复用的配合上,给你梳理几个可行的解决方案:
1. 替换自定义SimpleTarget为Glide原生的into(ImageView)
你现在用了SimpleTarget来手动设置Bitmap,但RecyclerView的ViewHolder是会被复用的:当快速滚动时,之前发起的异步加载任务完成后,会把图片设置到已经被复用给其他position的ImageView上,这就是图片串位的核心原因。
Glide自带的into(ImageView)内部已经做了ViewHolder复用的适配——它会自动跟踪View的状态,当View被复用或者滚动出屏幕时,会取消之前的加载任务,避免旧图片错位显示。修改你的ImageLoaderHelper代码:
public class ImageLoaderHelper { public static void getImageFromUrl(String url, final ImageView imageView, String signature) { if(url != null && !url.isEmpty()) { Glide.with(imageView.getContext()) .load(url) .asBitmap() .diskCacheStrategy(DiskCacheStrategy.RESULT) // 非必要的话建议去掉skipMemoryCache,后面会解释 // .skipMemoryCache(true) .signature(new StringSignature(signature.trim())) .into(imageView); // 直接传入ImageView,无需自定义Target } else { Glide.clear(imageView); imageView.setImageBitmap(null); } } }
2. 移除不必要的skipMemoryCache(true)
你当前设置了跳过内存缓存,这会导致每次滚动都要重新从磁盘或网络加载图片,不仅加载速度变慢,还会加重复用场景下的图片错位概率——因为没有内存缓存兜底,新的加载请求还没完成时,旧的加载任务先完成就会覆盖当前item的图片。如果不是业务上必须要禁用内存缓存,建议去掉这个配置。
3. 绑定ViewHolder前先清理旧内容
在onBindViewHolder绑定新数据之前,先主动清理ImageView的旧图片,确保不会残留之前复用的内容:
@Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if(holder instanceof NewsViewHolder) { NewsViewHolder newsViewHolder = (NewsViewHolder) holder; // 先清理旧图片,避免复用残留 Glide.clear(newsViewHolder.ivImage); newsViewHolder.ivImage.setImageBitmap(null); final Article article = articleList.get(position); newsViewHolder.tvName.setText(article.getTitle()); newsViewHolder.tvDescription.setText(article.getDescription()); ImageLoaderHelper.getImageFromUrl(article.getUrlToImage(), newsViewHolder.ivImage, signatureCache); newsViewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { onNewsItemClickListener.onNewsItemClick(article); } }); } }
4. 考虑升级Glide版本
Glide 3.8.0是比较老旧的版本了,里面存在一些已经在新版本中修复的复用场景bug。如果项目允许的话,建议升级到Glide 4.x系列(注意API有一些变化,需要适配),新版本对RecyclerView的适配更加完善,能从根源减少这类错位问题。
内容的提问来源于stack exchange,提问作者Christian Leonard

