Hey @TWiStErRob ,
I came across your post on stackoverflow.
Question :
I am using the recyclerview / listview to load the bitmap's.
I would like to know which context use to avoid unused request completions? Currently I am using getContext() directly to create my adapter. I don't want to pass fragment's / activity context to adapter creation as it might leak.
Any inputs on this regards would be highly appreciated.
Thanks!
Manju
getContext should return the Activity too as far as I know.
Adapters shouldn't really leak:
If anything in this list is destroyed, anything below is destroyed as well, so it should be safe to pass stuff down.
If you have an unreachable strongly connected component in the GC graph, it'll still be collected. For example if all of a, b, e is unreachable from all GC roots (can be anything else) they'll be collected:
![]()
I'm open to learning why this approach may leak though.
You can pass a RequestManager to the adapter so it can be used anywhere and the user of the adapter has to decide. So when you create the adapter you can say:
new MyAdapter(Glide.with(MyFragment.this), data) // or MyActivity.this; qualified only in case it's an inner class
In onBind: manager.load(...)...
Thanks @TWiStErRob ,
Yeah what you mentioned above make sense. However when I took a look at the heap dump in my app, views were hanging on to activity. I think that could be source of leak. I don't know for sure. I am still investigation on that. Meanwhile I would like to know is there anyway we can reduce the memory footprint of the glide? Like not hanging on to the allocated memory when the fragments are destroyed?
Heap dump screenshot attached

If you see screenshot of the heap dump, You can see Glide eats up most of my heap space. Is there any other way I can reduce the memory footprint?
Meanwhile I'll try to inject the RequestManager to my adapter as you mentioned here and see the result.
Ps : All our image request are done with .asBitmap() in recycler list & grid view.
Thanks!
Manju
You say views are hanging on to activity, that's normal: View.getContext returns that. The activity should also hang on to the views somehow (possibly indirectly). The question is: who else is hanging on to the views? If you suspect a leak, check if the activity should be alive or not, if it should be dead, do a shortest path to GC root and that should point out the leak.
If you're really stuck with the leak feel free to hit me up on Hangouts, I'm by no means an expert on them, but I'll try to help.
Regarding Glide memory usage: you can disable memory cache (that hash map), but that won't help your app's performance (imagine the use case when a user opens the same product right after she closed it). Your memory usage would be low, but who really cares about that? If you want to use the memory retained by the memory cache, just use it; Glide will surrender and vacate it to you when needed as far as I know (there's a callback for low memory which should handle this). Same with bitmap pool. If you run into OOMs & you take a heap dump & it shows Glide is retaining too much, then there's a problem: but still usually just showing unnecessarily large Bitmaps. I don't remember any leaks by Glide that wasn't somehow a usage error.
To help investigating memory leaks I suggest you put a button on your UI which calls Glide.get(context).clearMemory(). Press it before taking a dump so Glide doesn't show up in dominators. But please only use it in production if you do have a really good reason for it.
Sure, I'll try to do all those, How about I use Glide.get(context).clearMemory() in our Application.onLowMemory() in production do you see any problem with that?
If you use the proper context as detailed in the SO answer (most specific) Glide already handles that for you, so it's redundant:
there's a callback for low memory which should handle this
see [Support]RequestManagerFragment.onLowMemory and RequestManager.onLowMemory.
Thanks a lot for all the support @TWiStErRob , All these information helps for my further investigation.
Feel free to ask more if you need info. Sometimes it feels like there's a missing book on the "secrets" of Glide, there are so much goodies hidden in the code.
Totally agreed! I am following https://futurestud.io/blog/glide-getting-started blog for the more info whenever I can.
I built a Utility that I am re-using to build our Glide images and Glide transformations. How can I check to make sure this is not leaking, as I need to pass in context as opposed to the RequestManager in order to perform the CropCircle and RoundedCorners transformations?
public static void glideTransform(Context context, String mode, String url, int placeholder,
ImageView imageView) {
if (mode.equals("roundedCorners")) {
Glide.with(context)
.load(url != null && !url.isEmpty() ? url : placeholder)
.bitmapTransform(new RoundedCornersTransformation(context, Math.round(Utils
.convertDpToPixel(3)), 1))
.into(imageView);
} else {
Glide.with(context)
.load(url != null && !url.isEmpty() ? url : placeholder)
.bitmapTransform(new CropCircleTransformation(context))
.into(imageView);
}
}
@AdamSHurwitz You can pass in both RequestManager and Context, there's nothing wrong with that (imagine a call from fragment to see why this is good). There's also a trick: each view has a context (view.getContext()) so you can get away with not passing the context in, so you could simply use Context context = imageView.getContext().getApplicationContext() for transformations if you wanted to avoid leaks. Whichever way you go (Context as param, or from ImageView), the key is to use getApplicationContext, but it's not fully necessary as the lifecycle of those transformations should end when the target is cleared. However if you cache those transformations (you could, because they're stateless), you must use app context, see the Glide class for example.
Tip declare the param as: @DrawableRes int placeholder.