RecyclerView图片错乱复用问题
由于开发排行榜过程中遇到些问题,这里统一做下记录,由于RecyclerView的缓存复用机制,所以会导致item的复用问题,当图片时尤为明显,例如用户列表中有头像的没头像的,这时明显能看到错乱问题。
直接说下2种方案,包括正确的不正确的,好的坏的:
1、直接每次都给图片设置setImageDrawable(),然后加载网络图片
这样的话,每次刷新的时候图片都会先被设置成setImageDrawable() 中的图片,然后加载完网络图片的时候才会显示出来。猛的一看没问题,但是这就会造成什么呢,当你刷新的时候列表图片会有一个闪动的过程,也就是: 网络图片->设置的图片->网络图片这么一个闪动过程。体验不好,我们需要实现当图片地址不变的时候图片也依旧显示不变就好了。
2、给每个item中的图片设置tag
这个是目前的比较靠谱的方案了吧,给图片设置tag(下文中的tag设置为了图片的url),当该图片没有tag的时候说明这里还没有开始复用,那么直接加载网络图片即可;当该图片有tag的时候并且tag和图片的url相同,说明是复用来的并且图片的url还是对的,那么这个图片直接加载即可;当图片的tag和图片url不同时,说明这个图片是复用来的,所以就需要把原来的图片先设置为你的占位符,然后加载网络图片。
以上就是整个逻辑了,伪代码如下:
if (TUtils.isEmpty(item.getHeadUrl())) {
holder.mImgAvatar.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_placeholder_avatar));
} else {
String avatarTag = (String) holder.mImgAvatar.getTag();//如果tag为null则说明是全新的视图,否则是复用来的视图
//如果有图片的TAG有并且和之前设置的一样,那么直接再次加载即可
if (null == avatarTag || avatarTag.equals(item.getHeadUrl())) {
Glide.with(holder.mImgAvatar)
.load(item.getHeadUrl())
.override(SizeUtils.dp2px(34))
.into(new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
holder.mImgAvatar.setImageDrawable(resource);
}
});
}
//如果和原来的tag不同,也就是url不同,那么就先清空原来的图片,然后加载新的图片
else {
holder.mImgAvatar.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_placeholder_avatar));
Glide.with(holder.mImgAvatar)
.load(item.getHeadUrl())
.override(SizeUtils.dp2px(34))
.into(new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
holder.mImgAvatar.setImageDrawable(resource);
}
});
}
}
holder.mImgAvatar.setTag(item.getHeadUrl());