为什么 Glide 在 notifydatasetchanged 时使项目 ImageView 闪烁

Why Glide blink the item ImageView when notifydatasetchanged

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

这是我的代码:

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

当我不使用缓存时,ImageViewnotifyDataSetChanged 方法被调用且 Glide 尚未完成加载位图时有一个空位图。

如果我使用下面的代码:

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

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

我想动态更新项目视图,所以我禁用了滑动缓存。

是否有解决此闪烁错误的解决方案?

非常感谢!

经过我多次尝试,使用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);
            }
        });

将 Glide 从版本 3 更新到版本 4,并为 RecyclerView setSupportsChangeAnimations(false) 解决了我的问题

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

就我而言,我通过在 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" />

另外不要忘记在 adaptersetHasStableIds(true); 并正确覆盖 getItemId() 方法。
参见:example how to do it

由于 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()

试试下面的 Glide.with(this).load(photoToLoad.getPath()).placeholder(imageView.getDrawable()).into(imageView);

对于那些使用 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)
        }
    }
}

None 之前的答案解决了我的问题,即查看器中的所有项目在更新时都在闪烁。就我而言,我使用的是

notifyItemChanged(Index)

如果您考虑一下,该项目会闪烁是有道理的,因为我专门告诉查看器更新列表中的该项目。在我的例子中,只有八个东西中的一个实际上在 viewholder 中得到更新,但我的代码只有一种方法可以 onBindViewHolder。好吧,事实证明 RecyclerView.Adapter class 有第二个 onBindViewHolder 函数,它允许您只更新部分查看器,如果这就是您所需要的。签名是

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

你可以阅读它 。这对我有用。