-1

I have a RecyclerView and inside of each row I have ImageView where I'm using Glide to set an image from URL. The problem is when the first time I open and try to scroll RecyclerView then only that images are downloaded. Obviously it'll save to cache and next time it won't be downloaded again.

I'd like images to be preloaded for the first time so that when a user will scroll he/she won't have to wait.

Please see the code:

@Override
public void onBindViewHolder(PostAdapter.MyViewHolder holder, int position) {
    try {
        Post post = postArrayList.get(position);
        if (checkNull(post.getDesc())) {
            setText(holder.postDesc, postArrayList.get(position).getDesc());
        } else if (checkNull(post.getUrl())) {
            setImage(holder.postImage, postArrayList.get(position).getUrl());
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

}

private void setImage(ImageView image1, String str) {
    image1.setVisibility(View.VISIBLE);
    Glide.with(context).load(str).
    diskCacheStrategy(DiskCacheStrategy.ALL)
            .into(image1);
}
Priyanka Singh
  • 40
  • 1
  • 14
  • Please clarify the purpose of your question: a) To load images without cache b) To preload images into cache before rendering list c) Your choice? :) – ror Jun 24 '20 at 19:56
  • @ror b) To preload images into cache before rendering list – Priyanka Singh Jun 25 '20 at 12:22

1 Answers1

4

As I understand, the question is: how to preload images with Glide? It wasn't clear before all the conversation happened.

This is actually quite simple and almost identical to loading an image into an ImageView. Glide has a preload() function available that will preload image from given URL. Select DiskCacheStrategy that is most likely fits your situation.

Glide.with(context) 
        .load(imageUrl) 
        .diskCacheStrategy(DiskCacheStrategy.SOURCE) 
        .preload();

Use preload(int width, int height) if you want to change the size of the resulting image.

Glide.with(context) 
        .load(imageUrl) 
        .diskCacheStrategy(DiskCacheStrategy.SOURCE) 
        .preload(width, height);

If your cached images do not actually cache follow this solution to add custom LruCache map.

A little test conducted

A test involved three different sizes ImageViews 100x100, 200x200 and 300x300 DP respectively. Glide was tasked to load an 8K image into 200x200dp ImageView. Then after a short delay load the same image into the 100x100dp ImageView and after another delay into 300x300dp ImageView.

The test shows that the original image was cached due to instant loading speed into 300x300dp ImageView.

Note: Toast messages pop-up right before the image loading starts.

Video proof:

(If the video link is broken try this link).

Glide 8K image loading and caching test

Update (a bit out of question scope): how to wait until all images are preloaded?

... rest of YourActivity class


private int imagesLoaded = 0;
private int totalImagesCount = 0;

private void preloadAllImages(ArrayList<String> imagesUrls) {
    totalImagesCount = imagesUrls.size();
    for (String url : imagesUrls) {
        preloadImage(url);
    }
}

private void preloadImage(String url) {
    Glide.with(this) 
            .load(url) 
            .diskCacheStrategy(DiskCacheStrategy.ALL)
            .listener(new RequestListener<Drawable>() {
                @Override
                public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                    // Handle exceptions differently if you want
                    imagesLoaded++;
                    if (imagesLoaded == totalImagesCount) {
                        startMainActivity();
                    }
                    return true;
                }

                @Override
                public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                    imagesLoaded++;
                    if (imagesLoaded == totalImagesCount) {
                        startMainActivity();
                    }
                    return true;
                }
            })
            .preload();
}
Jenea Vranceanu
  • 4,530
  • 2
  • 18
  • 34
  • Thanks for the reply. The thing is inside onBindViewHolder, I written [Glide.with(context)].......So when I scroll that time it'll download and store, but I want on Splash Screen itself. So when user scroll, it won't download. – Priyanka Singh Jun 25 '20 at 12:24
  • 1
    The code I presented above you can use wherever you like. Copy it to your SplashScreen, get `postArrayList`, loop through `postArrayList` and invoke for each image the code I presented above. You can do that even from your `Application` class. – Jenea Vranceanu Jun 25 '20 at 12:53
  • So if I'll loop through images inside Spalsh, then in onBindViewHolder what I 'll write for images? Same thing? Can you post an answer please? – Priyanka Singh Jun 25 '20 at 12:56
  • 1
    Within `onBindViewHolder` you won't need to change anything. Your images, if they already loaded and cached, will be displayed instantly. If some image are still loading - they will load faster as the downloading is already in process. – Jenea Vranceanu Jun 25 '20 at 12:58
  • I heard one thing about Glide that, Glide resizes the image as per the dimension of the ImageView. See this [ https://medium.com/@multidots/glide-vs-picasso-930eed42b81d ] Then in our case will it again download and resize accroding to adpter row imageview size? Because in Spalsh screen it'll download actual image right? – Priyanka Singh Jun 25 '20 at 13:02
  • 1
    It is true about Glide's image resizing when loading into an ImageView. It should not load the same image twice if the size required for the next loading is equal or smaller than the size of the cached image. Looks like Glide actually caches image of original size and then resizes it when required. I'll post an update. – Jenea Vranceanu Jun 25 '20 at 14:59
  • Above is image. Can you send video link? – Priyanka Singh Jun 25 '20 at 15:20
  • Let me inplement in Spalsh Screen and test. I'll come back to you and if it's working then I'll accept and upvote your answer. Thanks. Please be online as well. – Priyanka Singh Jun 25 '20 at 15:23
  • One doubt: How will I get to know that Glide downloaded and cached Image from URL. Because after cached all images only I'll close. I'm pausing for 2 seconds using handler. – Priyanka Singh Jun 25 '20 at 15:32
  • 1
    Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/216650/discussion-between-jenea-vranceanu-and-priyanka-singh). – Jenea Vranceanu Jun 25 '20 at 15:34
  • Okay check my reply please – Priyanka Singh Jun 25 '20 at 16:12
  • Thank you very very much dear! – Priyanka Singh Jun 25 '20 at 18:04
  • Can you please check: https://stackoverflow.com/questions/62619895/how-to-get-image-path-which-is-stored-and-downloaded-by-glide-using-url-in-andro – Priyanka Singh Jun 28 '20 at 08:16
  • 1
    @PriyankaSingh, ok. – Jenea Vranceanu Jun 28 '20 at 09:10
  • Please see the chat, I had in that question. – Priyanka Singh Jun 28 '20 at 09:11
  • 1
    I cannot. It is private. – Jenea Vranceanu Jun 28 '20 at 09:12
  • I meant in Question's comments. [Not in personal discussion] – Priyanka Singh Jun 28 '20 at 09:19
  • Can you help? https://stackoverflow.com/questions/62783444/why-does-multipart-pdf-is-not-able-to-upload-in-api-using-retrofit-2-in-android – Priyanka Singh Jul 08 '20 at 07:17