Glide Version: 3.7.0
Device/Android Version: Nexus 5 with Android 6.0.1 (Build MMB29Q)
Issue details / Repro steps / Use case background:
I noticed that when using thumbnail() with a request on an already loaded image which should be cached there still is a slight delay when setting the thumbnail image before the final image is placed into the image view. Please see this Gist. The issue can be best reproduced with an empty cache, for instance if the application is started for the first time.
The first image is loaded into image1 when the Activity is created. When the button is clicked a second image is loaded into image2 with a thumbnail request on the first image. I would assume that the first image is displayed immediately until the second image has finished loading. However there is a slight moment where image2 is empty. The placeholder image set via the src attribute is gone, then either the first image is set after a delay followed by the second image or the second image is displayed after loading without the thumbnail.
In MainActivity when I replace IMAGE_2_LARGE by IMAGE_1_SMALL inside onClick at line 37 and remove the thumbnail() request the first image is immediately displayed in image2 after the button has been clicked. So it seems to have something to do with thumbnail().
Glide load line:
public class MainActivity extends AppCompatActivity {
private static final String IMAGE_1_SMALL =
"https://images.unsplash.com/photo-1452475168325-672188dc4dc3?h=600&w=600&fit=crop";
private static final String IMAGE_2_LARGE =
"https://images.unsplash.com/photo-1448518184296-a22facb4446f?h=1200&w=1200&fit=crop";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageView image1 = (ImageView) findViewById(R.id.image1);
final ImageView image2 = (ImageView) findViewById(R.id.image2);
final Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
final DrawableRequestBuilder<String> thumbnailRequest =
Glide.with(MainActivity.this)
.load(IMAGE_1_SMALL)
.dontAnimate();
Glide.with(MainActivity.this)
.load(IMAGE_2_LARGE)
.thumbnail(thumbnailRequest)
.dontAnimate()
.into(image2);
}
});
Glide.with(this)
.load(IMAGE_1_SMALL)
.dontAnimate()
.into(image1);
}
}
Layout XML:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="10dp">
<ImageView
android:id="@+id/image1"
android:layout_width="200dp"
android:layout_height="200dp"
android:src="@drawable/placeholder"/>
<ImageView
android:id="@+id/image2"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginTop="10dp"
android:src="@drawable/placeholder"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Load image"/>
</LinearLayout>
Awesome report, thanks!
What you're seeing is a cache miss, which can be best diagnosed by enabling logging, you'll see that the transformations are different.
Take a look at into(ImageView)'s source and notice there's a little trick going on there. However when you use .thumbnail() you don't have any transformations, so it's almost the same as calling .dontTransform(), which doesn't match the previously automatically added .fitCenter(), which is the default value of ImageView.scaleType.
As for the placeholder, setting anything as android:src won't do much for you because Glide immediately clears that and replaces it with the .placeholder() you passed in, which is null by default. The best course of action is to set tools:src so you have something in the preview, but it won't incur any runtime penalty (android:src will force the view to load the drawable on inflate, possibly unnecessarily), and add .placeholder(R.drawable.placeholder) in your code whenever you need it.
Thanks for your quick response!
android:src is not the problem in my scenario. I just added it for sake of the example source code. However the slight delay before the thumbnail is loaded is actually a problem because it leads to a visible "flickering" in my app.
How can I force Glide to use the cached image for the thumbnail() call or otherwise prevent the flickering?
Oh, sorry, forgot to write down a sentence there: just add .fitCenter() to your thumbnail request so that it matches the other load fully and hits the cache.
Thank you very much! Adding .fitCenter() to the thumbnail request indeed fixed the flickering :+1: :)
@TWiStErRob I have almost same problem here.
I'm sure that thumbnail is in cache, because it is loaded in previous recycler view.
I have problem with flickering here. First appears imageview background then thumbnail flickers, and after that flickers full image size photo.
Shouldn't be thumbnail instantly loaded into ImageView when view is binded?
DrawableRequestBuilder<String> thumbnailRequest = Glide
.with(holder.itemView.getContext())
.load(thumbUrl)
.fitCenter();
Glide.with(holder.itemView.getContext())
.load(imgurl)
.thumbnail(thumbnailRequest)
.into(holder.ivMainPhoto);
@rule-po add a LoggingListener or check wiki to see the loaded sizes and diagnose cache hits/misses.
I have problem with flickering here. First appears imageview background then thumbnail flickers, and after that flickers full image size photo.
I'm assuming by "flickers" you mean cross-fades, in which case all you need is .dontAnimate() on both the thumbnail and the main load.
Shouldn't be thumbnail instantly loaded into ImageView when view is binded?
Yes, that's true. To hit the cache you need to match size (w/h), transformation (fitCenter/centerCrop), type (drawable/bitmap). Check with the above tools which one is mismatching. Mind you that the hit will always happen if there was enough memory to hold the "old" image in memory cache. Since you said it was in another recycler view, it's possible that the memory pressure evicted them from the memory cache.
If these don't help, please open a new issue with more information!
Most helpful comment
@TWiStErRob I have almost same problem here.
I'm sure that thumbnail is in cache, because it is loaded in previous recycler view.
I have problem with flickering here. First appears imageview background then thumbnail flickers, and after that flickers full image size photo.
Shouldn't be thumbnail instantly loaded into ImageView when view is binded?