Glide: Loading wrong image after scrolling down and up

Created on 18 Jun 2016  路  24Comments  路  Source: bumptech/glide

Glide Version:
I'm using Glide v3.7.0

Integration libraries:
HttpAsync & Gson

Device/Android Version:
Tested on Galaxy s5 SM-G900H and Galaxy A5 A500H both android 5

Issue details / Repro steps / Use case background:

and the problem is that when i scroll a few pages down and come back to the top i notice that a few (one or sometimes more) viewholders has wrong images.

each page has 30 items and 10 load request can be sent.

after loading this wrong image when i refresh the list it still has same wrong image even though the URL is correct. but after reopening activity it's fine

Glide load line / GlideModule (if any) / list Adapter code (if any):

Glide.with(context)
                    .load(game.getLogo_300())
                    .placeholder(R.drawable.no_game)
                    .error(R.drawable.no_game)
                    .crossFade()
                    .into(holderGames.gameImageView);

URLs are not null and it's simply inside onBindViewHolder

Layout XML:

<ImageView
                    android:id="@+id/imgGameImage"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal|top"
                    android:src="@drawable/no_game"/>

Stack trace / LogCat:

No relevant logs
question repro-needed

Most helpful comment

@hiteshsahu "This version of clear only works if you're using ViewTarget or a subclass", does SimpleTarget match that? Without ViewTarget you need to clear the exact target you pass to into() which can be done like this:

if (holder.currentTarget != null) Glide.clear(holder.currentTarget);
holder.currentTarget = Glide.with(context) .... into(new SimpleTarget...);

Note: Please review the Glide way of generating a Palette; it doesn't have this problem and also won't show the wrong color for an image when you fling due to async palette generation.

All 24 comments

it's simply inside onBindViewHolder

From this I assume that Glide.with is not inside an async call

URLs are not null

This sounds like the Glide.with may be conditional. Do you have code like this?

onBindViewHolder() {
    ...
    if (something) {
        Glide.with...;
    }
}

If yes, you need to add else { Glide.clear(holderGames.gameImageView); }.

@TWiStErRob Thanks for reply

If yes, you need to add else { Glide.clear(holderGames.gameImageView); }.

but no. there is no condition.

Is there a chance you can make a small project to repro this?

What is game and how do you acquire it?
What is the type of getLogo_300?
Which layout manager do you use?

What is game and how do you acquire it?

game is an item of a List<GameData> filled with data acquired from server and

What is the type of getLogo_300?

getLogo_300 returns String of image path

Which layout manager do you use?

GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3);
        gridLayoutManager.setSpanSizeLookup(spanSizeLookup);
GridLayoutManager.SpanSizeLookup spanSizeLookup = new GridLayoutManager.SpanSizeLookup() {
        @Override
        public int getSpanSize(int position) {
            if (position == 0) {
                    return 3;
                else
                    return 1;
            }
       }
}

even without SpanSizeLookup it's the same

No more ideas, can you try to extract a small repro or link/send your project?

Found something
Only when i set cache strategy to source it works fine! but i want Glide Not Picasso :(

diskCacheStrategy(DiskCacheStrategy.SOURCE)

That shouldn't make a difference... Try with RESULT cache, but clear the caches first. Maybe some images have wrong images in cache, but this seems weird because it looks ok at first.

Another thing to try is RESULT cache and skipMemoryCache(true).

Another thing to try is RESULT cache and skipMemoryCache(true).

No. it just works when SOURCE is set. even after clearing cache

@sajadshokri any chance of a repro app?
@sjudd any ideas?

@TWiStErRob I'll try to extract a sample source

Please reopen if you get a chance to repro it.

While I hope I'm not diluting the context of this issue, I appear to be having a similar issue using glide in a recyclerview adapter. My app has another very similar recyclerview setup where everything works perfectly, and I essentially reused code from that setup to create this other recyclerview. The ONLY difference between the two recyclerview patterns is that the first one has pictures loading into every view, while the second one has only one view with an image (at this point in time).

To try and troubleshoot, I tried placing placeholder images in any view which didn't already have an image available.

Any tips on what helpful information I could provide to make debugging easier? I could create a stripped down version of the app, if that is beneficial, as it is rather complex at this point in time.

Thanks a lot!

@adventurist your sounds like a simple case of if (hasImage) Glide.....into(imageView); else Glide.clear(imageView);. If there's no image you need to tell Glide to forget about it (normally done in into), because of the recycling.

I certainly hope so! I am calling Glide.clear in an if/else statement like suggested, but my syntax is different from the example. Will modify it and report my findings!

UPDATE: Simply setting Glide.clear if the image returns null didn't work, BUT the second suggestion in the example you provided DID work! (Always calling Glide.with(activity).load(<METHOD WHICH CAN RETURN NULL>).myImageView)works GREAT!

In case it helps anyone, here's what I have:

Glide.with(mActivity)
                                .load(getImg(statusItem))
                                .centerCrop()
                                .diskCacheStrategy(DiskCacheStrategy.RESULT)
                                .into(stHolder.imageView);

And the getImg method:

public String getImg(StatusItem mItem) {
        if ((mItem.getImage()) == null) return null;
        String url = mItem.getImage();
        return url;
    }

Thanks a lot!

@TWiStErRob There has same problem with this sample:
https://github.com/ioneday/ImageSelector

and only use diskCacheStrategy(DiskCacheStrategy.SOURCE) can resolve it.

Sorry for my poor Engslih...

@chenxiaojin please open a new issue and fill in the full issue template.

Nothing worked in my case except setImageBitmap(null); to my imageview just before loading image in my viewholder with glide.
Hope it help somebody.

@hiteshsahu try Glide.clear(imageView); to make sure you don't conflict with Glide. It should have a very similar effect, with the exception that it will keep the internal Glide state correct. This version of clear only works if you're using ViewTarget or a subclass (=default if you use load(ImageView)).

UnfortunatelyGlide.clear(imageView); doesn't seems to be working.

Glide started to load wrong images if i use Glide.clear(((MediaViewHolder) holder).getMediaImage()); instead of ((MediaViewHolder) holder).getMediaImage().setImageBitmap(null);.

Is it wrong if I clear bitmap before loading in my ViewHolder. I am using glide to generate palettes you can see my snippet

// What I tried :- clear wrong album image manually
((MediaViewHolder) holder).getMediaImage().setImageBitmap(null);

// TWiStErRob suggestion :- let glide handle cleaning
//Glide.clear(((MediaViewHolder) holder).getMediaImage());

Glide.with(context)
    .load(ContentUris.withAppendedId(AppContants.sArtworkUri, getItem(position).getAlbumId()))
    .asBitmap()
    .placeholder(R.drawable.default_artist)
    .diskCacheStrategy(DiskCacheStrategy.ALL).centerCrop()
    .error(Utils.generatePlaceHolder(getItem(position).getTitle()))
    .into(new SimpleTarget<Bitmap>() {
        @Override
        public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
            // you can do something with loaded bitmap here

            ((MediaViewHolder) holder).getMediaImage().setImageBitmap(resource);

            Palette.from(resource).generate(new Palette.PaletteAsyncListener() {
                @Override
                public void onGenerated(Palette palette) {
                    // Get the "vibrant" color swatch based on the bitmap
                    Palette.Swatch vibrant = palette.getVibrantSwatch();
                    if (vibrant != null) {

                        // Set the background color of a layout based on the vibrant color
                        ((MediaViewHolder) holder).getContainerbg().setBackgroundColor(vibrant.getRgb());

                    }
                }
            });
        }

        @Override
        public void onLoadFailed(Exception e, Drawable errorDrawable) {
            super.onLoadFailed(e, errorDrawable);

            ((MediaViewHolder) holder).getMediaImage().setBackground(errorDrawable);

            ((MediaViewHolder) holder).getContainerbg().setBackground(generateRandomGradient(getItem(position).getTitle()));
        }
    });

@hiteshsahu "This version of clear only works if you're using ViewTarget or a subclass", does SimpleTarget match that? Without ViewTarget you need to clear the exact target you pass to into() which can be done like this:

if (holder.currentTarget != null) Glide.clear(holder.currentTarget);
holder.currentTarget = Glide.with(context) .... into(new SimpleTarget...);

Note: Please review the Glide way of generating a Palette; it doesn't have this problem and also won't show the wrong color for an image when you fling due to async palette generation.

Perfect !! worked like charm. many thanks !!

it's simply inside onBindViewHolder

From this I assume that Glide.with is not inside an async call

URLs are not null

This sounds like the Glide.with may be conditional. Do you have code like this?

onBindViewHolder() {
    ...
    if (something) {
        Glide.with...;
    }
}

If yes, you need to add else { Glide.clear(holderGames.gameImageView); }.

I have a condition like this but adding GlideApp.with(context).clear(imageview); does not solve my problem

Was this page helpful?
0 / 5 - 0 ratings

Related issues

r4m1n picture r4m1n  路  3Comments

billy2271 picture billy2271  路  3Comments

Morteza-Rastgoo picture Morteza-Rastgoo  路  3Comments

kooeasy picture kooeasy  路  3Comments

MrFuFuFu picture MrFuFuFu  路  3Comments