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
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.withis not inside an async callURLs are not null
This sounds like the
Glide.withmay 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
Most helpful comment
@hiteshsahu "This version of clear only works if you're using ViewTarget or a subclass", does
SimpleTargetmatch that? WithoutViewTargetyou need to clear the exact target you pass tointo()which can be done like this: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.