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?
Best way to cancel the image request is to call Glide.clear()
Here is the sample code.
Glide.with(context).clear(imageviewRef);
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With