为什么在notifydatasetchanged时Glide会导致项目的ImageView闪烁

20

我正在使用 Glide 3.7.0RecyclerView。当刷新(调用notifyDataSetChanged)时,项目视图总是闪烁。

这是我的代码:

Glide
  .with(context)
  .load(filepath)
  .diskCacheStrategy(DiskCacheStrategy.NONE)
  .skipMemoryCache(true)
  .dontAnimate()
  .into(imageview);

当我不使用缓存时,在调用 notifyDataSetChanged 方法且 Glide 还未完成加载位图时,ImageView 的位图为空。

如果我使用以下代码:

Glide
  .with(context)
  .load(filepath)
  .dontAnimate()
  .into(imageview);

然后项目中的ImageView不再闪烁(使用缓存)。

我想动态更新项目视图,因此禁用了 Glide 缓存。

有没有解决这个闪烁问题的解决方案?

非常感谢!

10个回答

31

经过我的多次尝试,只是使用SimpleTarget解决了我的问题。谢谢!

Glide
.with(context)
.load(filepath)
.asBitmap()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.dontAnimate()
.into(new SimpleTarget<Bitmap>() {

            @Override
            public void onResourceReady(Bitmap arg0, GlideAnimation<? super Bitmap> arg1) {
                // TODO Auto-generated method stub
                holder.mItemView.setImageBitmap(arg0);
            }
        });

5
SimpleTarget现已弃用。 - Aba
3
我刚试了所有的解决方案,但唯一有效的是这个答案。非常感谢,你救了我的一天。由于SimpleTarget现在已经过时了,你可以使用CustomTarget。 - setare maghari
现在使用CustomTarget,因为SimpleTarget已过时。 - aslamhossin
1
但仍然无效,图像仍在闪烁。 - Dhara Patel
不管我做什么都不起作用。 - Anthony
图片还在闪烁,对我也不起作用。 - navya sree

5

将Glide从版本3升级到4,并为RecyclerView设置setSupportsChangeAnimations(false),这解决了我的问题。

RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator();
if (animator instanceof SimpleItemAnimator) {
    ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
}

对我不起作用 - Dhara Patel

4

由于SimpleTarget已过时,请尝试使用以下解决方案:

GlideApp.with(SOMETHING)
                                .load("WHAT")
                                .dontAnimate()
                                .let { request ->
                                    if(imageView.drawable != null) {
                                        request.placeholder(imageView.drawable.constantState?.newDrawable()?.mutate())
                                    } else {
                                        request
                                    }
                                }
                                .into(imageView)

你还可以创建漂亮的Drawable扩展,以进行真正的复制:
import android.graphics.drawable.Drawable

fun Drawable.copy() = constantState?.newDrawable()?.mutate()

2

还要记得在您的适配器中setHasStableIds(true);,并正确地重写getItemId()方法。
请参见:如何操作的示例


2
尝试以下代码: Glide.with(this).load(photoToLoad.getPath()).placeholder(imageView.getDrawable()).into(imageView);

2

在我的情况下,我通过在imageView上使用定义的尺寸来解决了这个问题。

<ImageView
        android:id="@+id/poster_imageview"
        android:layout_width="130dp"
        android:layout_height="183dp"
        android:adjustViewBounds="true"
        android:scaleType="centerCrop"
        android:src="@drawable/placeholder" />

2
若您正在使用Kotlin和BindAdapter,以下内容可能有所帮助:
@BindingAdapter("imageUrl", "error", "placeholder")
fun ImageView.loadImage(imageUrl: String?, error: Drawable, placeholder: Drawable) {

    if (imageUrl.isNullOrBlank()) {
        setImageDrawable(error)
    } else {

        try {
            Glide
            .with(context)
            .asBitmap()
            .load(imageUrl)
            .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
            .skipMemoryCache(true)
            .dontAnimate()
            .into(object: CustomTarget<Bitmap?>() {
                override fun onResourceReady(
                    resource: Bitmap,
                    transition: Transition<in Bitmap?>?,
                ) {
                    setImageBitmap(resource)
                }

                override fun onLoadCleared(placeholder: Drawable?) {
                    setImageDrawable(placeholder)
                }

            })
        } catch (e: Exception) {
            setImageDrawable(placeholder)
        }
    }
}

0

yourRecyclerView.itemAnimator = null

你的RecyclerView.itemAnimator = null


这不是问题的答案。一旦你有足够的声望,你就可以评论任何帖子; 相反,提供不需要询问者澄清的答案。-来自审阅 - Junaid Khalid

0

之前的回答都没有解决我的问题,即在更新时视图持有者中的所有项目都会闪烁。在我的情况下,我正在使用

notifyItemChanged(Index)

如果你仔细想一下,这个项目会闪烁是有道理的,因为我明确告诉了viewholder要更新列表中的那个项目。在我的情况下,只有八个项目中的一个实际上得到了更新,但我的代码只有一种方法onBindViewHolder。好吧,事实证明RecyclerView.Adapter类有第二个onBindViewHolder函数,允许你只更新viewholder的部分内容,如果这是你所需要的全部。签名是

onBindViewHolder(holder: CommentViewHolder, position: Int, payloads: MutableList<Any>)

你可以在这里阅读相关内容。这对我很有帮助。


0
对我来说,解决方案是在Glide构建器中添加.placeholder()
            Glide.with(view)
            .load(picture)
            .placeholder(placeholderImg)
            .into(view)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接