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
  • 27,060
  • 21
  • 118
  • 148
thedarkpassenger
  • 7,158
  • 3
  • 37
  • 61

3 Answers3

7

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

 Glide.with(context).clear(imageviewRef);
Kartheek
  • 7,104
  • 3
  • 30
  • 44
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
  • 12,479
  • 7
  • 64
  • 91
  • 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,722
  • 5
  • 40
  • 58
Yesha Shah
  • 408
  • 1
  • 5
  • 17