为什么 Glide 在 notifydatasetchanged 时使项目 ImageView 闪烁
Why Glide blink the item ImageView when notifydatasetchanged
我正在使用 Glide 3.7.0 和 RecyclerView
。项目视图在刷新时总是闪烁(调用notifyDataSetChanged
)。
这是我的代码:
Glide
.with(context)
.load(filepath)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.dontAnimate()
.into(imageview);
当我不使用缓存时,ImageView
在 notifyDataSetChanged
方法被调用且 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" />
另外不要忘记在 adapter
中 setHasStableIds(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>)
你可以阅读它 。这对我有用。
我正在使用 Glide 3.7.0 和 RecyclerView
。项目视图在刷新时总是闪烁(调用notifyDataSetChanged
)。
这是我的代码:
Glide
.with(context)
.load(filepath)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.dontAnimate()
.into(imageview);
当我不使用缓存时,ImageView
在 notifyDataSetChanged
方法被调用且 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" />
另外不要忘记在 adapter
中 setHasStableIds(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>)
你可以阅读它