20

I am using Glide 3.7.0 with RecyclerView. The item view always blinks when refreshing (calling notifyDataSetChanged).

Here is my code:

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

When I use no cache, the ImageView has a null Bitmap when notifyDataSetChanged method is called and Glide hasn't finished loading the bitmap.

If I use the code below:

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

Then the item ImageView does not blink anymore (using cache).

I want to update the item view dynamically, so I disable the glide cache.

Are there any solutions to solve this blink bug?

Thank you very much!

Jared Rummler
  • 37,824
  • 19
  • 133
  • 148
Yoyoy Chu
  • 629
  • 1
  • 5
  • 10

10 Answers10

31

After my many tries, just use SimpleTarget solved my problem thank you!

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);
            }
        });
Yoyoy Chu
  • 629
  • 1
  • 5
  • 10
5

Update Glide from version 3 to 4 and setSupportsChangeAnimations(false) for RecyclerView solved problem for me

RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator();
if (animator instanceof SimpleItemAnimator) {
    ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
}
Sᴀᴍ Onᴇᴌᴀ
  • 8,218
  • 8
  • 36
  • 58
MakBeard
  • 280
  • 4
  • 7
4

since SimpleTarget is deprecated try this solution:

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

you can also create nice extension for drawable to make REAL copy:

import android.graphics.drawable.Drawable

fun Drawable.copy() = constantState?.newDrawable()?.mutate()
Filipkowicz
  • 639
  • 6
  • 17
2

In my case, I solved the issue by using defined dimensions on my 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

Also don't forget to setHasStableIds(true); in your adapter and properly override getItemId() method.
See: example how to do it

t0m
  • 3,004
  • 31
  • 53
Daniil Andashev
  • 154
  • 1
  • 9
2

try the below Glide.with(this).load(photoToLoad.getPath()).placeholder(imageView.getDrawable()).into(imageView);

Ashwin Khadgi
  • 292
  • 4
  • 12
1

For those who are working with kotlin and BindAdapter, this worked for me:

@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

None of the previous answers solved my problem, which was all the items in the viewholder blinking on update. In my case I was using

notifyItemChanged(Index)

If you think about it, it makes sense that the item would blink since I was specifically telling the viewholder to update that item in the list. In my case only one of eight things was actually getting updated in the viewholder, but my code only had one way to onBindViewHolder. Well it turns out the RecyclerView.Adapter class has a second onBindViewHolder function that allows you to only update part of your viewholder if that's all you need. The signature is

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

And you can read about it here. This worked for me.

szaske
  • 1,887
  • 22
  • 32
0

yourRecyclerView.itemAnimator = null

  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/32220359) – Junaid Khalid Jul 15 '22 at 09:26
0

For me the solution was to add .placeholder() to Glide builder:

            Glide.with(view)
            .load(picture)
            .placeholder(placeholderImg)
            .into(view)
FarVoyager
  • 49
  • 4