Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - How to cancel the image request when preloading images with the Glide library?

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?

like image 312
thedarkpassenger Avatar asked Mar 06 '23 15:03

thedarkpassenger


2 Answers

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

 Glide.with(context).clear(imageviewRef);
like image 70
Kartheek Avatar answered Mar 09 '23 07:03

Kartheek


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.

like image 32
Angel Koh Avatar answered Mar 09 '23 05:03

Angel Koh