4

Note: This question is different from this question as no answers given for the question explain how to cancel the image request which we make for preloaded image.

I have an infinite list(RecyclerView). I need to preload images of next 'x'(read 3) items from the last bound item of the RecyclerView. Also, when a particular Viewholder is detached from the window, I need to cancel the preload image request if it is already not successful.

I have achieved it in the following way.

Map<Integer, SimpleTarget> simpleTargetMap = new HashMap<>();

public void preloadImage(int position, Context context, String imageUrl) {
    SimpleTarget simpleTarget = new SimpleTarget() {
      @Override
      public void onResourceReady(@NonNull Object resource, @Nullable Transition transition) {
        simpleTargetMap.remove(position);
      }
    };
    Glide.with(context)asBitmap().load(imageUrl).into(simpleTarget);
    simpleTargetMap.put(position, simpleTarget);
}


  @Override
public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) {
    super.onViewDetachedFromWindow(holder);
    SimpleTarget simpleTarget = simpleTargetMap.get(holder.getAdapterPosition());
    Glide.with(context).clear(simpleTarget);
    simpleTargetMap.remove(holder.getAdapterPosition());
}

I am able to achieve the desired result. But I am facing memory issues with this approach. If I don't use the preloading, my memory usage is between 150-200 mb. But if I start using the preload, the memory usage jumps to 250-300 mb. After taking a heap dump, I see a lot of Bitmap objects which are not there(not as many) if I don't use preload.

So what is the best way to preload an image in Glide where I can also cancel the image request in the future? And if I don't use SimpleTarget, is there any way of cancelling an image request based only of the imageUrl?

Zoe stands with Ukraine
  • 25,310
  • 18
  • 114
  • 149
thedarkpassenger
  • 6,630
  • 2
  • 34
  • 57

3 Answers3

6

Best way to cancel the image request is to call Glide.clear()
Here is the sample code.

 Glide.with(context).clear(imageviewRef);
Kartheek
  • 7,020
  • 3
  • 28
  • 43
1

In your case, instead of preloading one item at a time, you should be using ListPreloader in conjunction with the RecyclerViewPreloader which handles the loading one batch at a time.

Refer to https://github.com/bumptech/glide/blob/master/library/src/main/java/com/bumptech/glide/ListPreloader.java and https://github.com/bumptech/glide/blob/master/integration/recyclerview/src/main/java/com/bumptech/glide/integration/recyclerview/RecyclerViewPreloader.java

 * Loads a few resources ahead in the direction of scrolling in any {@link AbsListView} so that
 * images are in the memory cache just before the corresponding view in created in the list. Gives
 * the appearance of an infinitely large image cache, depending on scrolling speed, cpu speed, and
 * cache size.

If you are adamant about creating a cancel mechanism yourself, then look at how Glide do it in their ListPreloader class. Specifically they use a requestManager to handle the cancelling. Below is their code snippet for cancelAll.

private void cancelAll() {
    for (int i = 0; i < maxPreload; i++) {
      requestManager.clear(preloadTargetQueue.next(0, 0));
    }
  }

PreloadTargetQueue is a custom inner class in that file.

Angel Koh
  • 11,377
  • 7
  • 59
  • 84
  • Thanks. earlier I didn't knew about the Preload library of glide. But after knowing about it, I am using that only for image prefetch. – thedarkpassenger Apr 27 '18 at 09:15
0

Load images into memory cache using preload method:

Glide.with(context)
        .load(url)
        .preload(500, 500);

You can later use the cached images using:

Glide.with(yourFragment)
    .load(yourUrl)
    .into(yourView);
Adinia
  • 3,660
  • 5
  • 41
  • 57
Yesha Shah
  • 388
  • 1
  • 5
  • 16