Glide image loading with application context

AndroidPerformanceAndroid Glide

Android Problem Overview


I am using glide for image loading in my android app, to avoid any crashes I am loading images with application context. What will be effect of this on performance of application and memory?

Android Solutions


Solution 1 - Android

> What will be effect of this on performance of application and memory?

Glide provides so many .with() methods for a reason: it follows lifecycle.

Imagine a Fragment that is dynamically added to an Activity. In its onCreateView method it starts a Glide load of a 3MB image. Now, what if the user presses the back button and the Fragment is removed or the whole activity is closed?

  • If you use with(getActivity().getApplicationContext()) nothing will happen, all 3MBs of data is downloaded and then decoded, cached, probably even set to the ImageView, which is then garbage collected, because the only reference to it was from Glide internals.
  • If you use with((Fragment)this) Glide subscribes to the Fragment's lifecycle events and as soon as the Fragment is stopped, the any outstanding request should be paused; and when destroyed, all pending requests be cleared. This means that the image download will stop midway and no more resources will be used by that dead Fragment.
  • If you use with(getActivity()) Glide subscribes to the Activity's lifecycle events and the same thing happens as above, but only when the Activity is stopped or destroyed.

So the best practice is to use the closest possible context/fragment to avoid unused request completions! (There's also a manual way to stop a load: Glide.clear(ImageView|Target).)


To apply this in practice try to use with(this) when possible, but when it's not, like in an adapter, or a centralized image loading method, pass in a RequestManager glide as an argument and use glide.load(..., for example:

static loadImage(RequestManager glide, String url, ImageView view) {
    glide.load(url).into(view);
}

or in adapter:

class MyAdapter extends WhichEveryOneYouUse {
    private final RequestManager glide;
    MyAdapter(RequestManager glide, ...) {
        this.glide = glide;
        ...
    }
    void getView/onBindViewHolder(... int position) {
        // ... holder magic, and get current item for position
        glide.load... or even loadImage(glide, item.url, holder.image);
    }
}

and use these from Activity/Fragment:

loadImage(Glide.with(this), url, findViewById(R.id.image));
// or
list.setAdapter(new MyAdapter(Glide.with(this), data));

Solution 2 - Android

A generic solution to sync Glide requests with the lifecycle of an owner. Can be called from anywhere: Activity, Fragment, RV Adapter, Custom View etc.

private fun RequestManager.syncWithLifecycleOwner(view: View): RequestManager {

val syncRequest = object : DefaultLifecycleObserver {
    override fun onStart(owner: LifecycleOwner) = onStart()
    override fun onStop(owner: LifecycleOwner) = onStop()
    override fun onDestroy(owner: LifecycleOwner) {
        onDestroy()
        owner.lifecycle.removeObserver(this)
    }
}

view.findViewTreeLifecycleOwner()?.lifecycle?.addObserver(syncRequest)

return this

}

You then can make a simple extension function like so:

fun ImageView.loadUrl(url: String) {
   Glide
      .with(context.applicationContext)
      .syncWithLifecycleOwner(this)
      .load(url)
      .into(this) 
}

findViewTreeLifecycleOwner() is present in the AndroidX Lifecycle lib. It provides the Activity or the Fragment View's lifecycle (viewLifecycleOwner) this specific ImageView is attached to. You will need to pass in application context from within the view, to make sure the Glide libs does not call the callbacks itself.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHariRamView Question on Stackoverflow
Solution 1 - AndroidTWiStErRobView Answer on Stackoverflow
Solution 2 - AndroidRvb84View Answer on Stackoverflow