How to Use Responsive Images to Speed Up Apps — Android Glide

Efficient image loading with Glide for faster, smoother app performance.
Apr 28 2022 · 5 min read

Introduction 

Loading images efficiently is very important, on every platform, be it android, iOS or the Web. It makes apps/websites faster and also saves users' internet bandwidth.

Today, we will answer these 4 questions —

  1. What is responsive image loading?
  2. Why is it important?
  3. Various approaches to providing responsive images
  4. How to implement it with the android Glide library

Let’s begin!

We are what we repeatedly do. Excellence, then, is not an act, but a habit. Try out Justly and start building your habits today!

1. What is responsive image loading?

1_fYs6uq3napLGDs1skNS_Bg.png

Responsive loading is the term where a client fetches exact or nearby resolution images that is required from the server.

Device resolution varies from device to device and to support high-quality images, most of the time we keep the multiple resolution images on the server.

With responsive images, instead of a server pushing for an exact resolution, the client chooses what it wants to use based on its own use cases.

2. Why is it important?

Loading 4k images on a 1080p device is very inefficient.

Not only you will end up making your apps slower, but you will also waste user’s internet bandwidth. Also, loading higher resolution images will slow down your app as GPU will have to render useless pixels.

It’s better to use different images based on device resolution. Clients can also load different resolution images based on the ImageView size.
i.e Image container can be a small thumbnail or full screen image and loading the same size image for both use case does not make sense.

Now you have a basic idea of what is responsive images and their importance.

Let’s explore the ways to implement it on servers.

3. Various approaches to providing responsive images

We will discuss 2 general ways.

  1. Servers provide available image sizes
  2. Servers allow dynamic image sizes

Let’s start with the first one.

1. Servers provide available image sizes

With this approach, server provides exact list of the available image sizes.

For example, you are developing a facebook app and you need to show feeds on home screen. You make an API call and you will receive following response from the server.
1_0h-F-5WeOaf3tcS5zx7PWg.png

As you can see, server provides low , high and vhigh images and client chooses the right one based on the use case.

However, this approach has a few drawbacks

  • Clients need to know in advance which exact resolutions are available and need to update code whenever it changes
  • Increases API response size as every image size has its own url. List can grow significantly if server supports more image sizes.

A better approach would be to provide available image sizes in a single URL.

Google I/O open source app suggests something like this

myserver.com/images/__w-200-400-600-800-1000__/session1.jpg

This single URL consists of all the supported resolutions for the images.

By default, this URL will serve the full size image. To get the image restricted to width 200px, replace __w-...__ by "w200":

myserver.com/images/w200/session1.jpg

And for 400px of width:

myserver.com/images/w400/session1.jpg

Too easy right? Yes, indeed.

We will later see how Glide can be configured to load responsive images with just a few lines of code!

2. Servers support dynamic image size

With this approach, servers don’t store different sizes of images. Instead, they generate required image size upon request and serve it.

By default, the URL will provide full-size image. However, you can add query parameters to fetch the exact image size.

For example, clients can use this URL to get 300x150 px images.

myserver.com/images/session1.jpg?size=300x150

The configuration and query parameters will defer from server to server. Usually, the API server will have documentation on how you can request specific image sizes.

Now, we have an idea about how servers can provide options to use responsive images.

Let’s explore how we can configure Glide to make use of this.

4. How to implement it with the android Glide library

The best way to use responsive images with Glide is to just register a module globally that will modify URLs based on view size.

Let’s start by adding a glide module

@GlideModule
class MyGlideModule : AppGlideModule() {
    override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
        registry.replace(String::class.java, InputStream::class.java, VariableWidthModelFactory())
    }
}

This snippet will register VariableWidthModelFactory in glide to handle String URLs.

In short, whenever an image is loaded with a string URL, this factory will get a callback and we will have a chance to modify the URL.

Let’s see implementation of VariableWidthModelFactory

class VariableWidthModelFactory : ModelLoaderFactory<String, InputStream> {
    override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader<String, InputStream> {
        return VariableWidthImageLoader(
                multiFactory.build(
                        GlideUrl::class.java,
                        InputStream::class.java
                )
        )
    }

    override fun teardown() {
        // Do nothing.
    }
}

The factory will just provide an instance of the VariableWidthImageLoader class and actual URL modification will happen inside that class.

Let’s see implementation of VariableWidthImageLoader

class VariableWidthImageLoader(concreteLoader: ModelLoader<GlideUrl?, InputStream?>?) :
        BaseGlideUrlLoader<String>(concreteLoader, ModelCache(500)) {

    override fun getUrl(model: String, width: Int, height: Int, options: Options): String {
        var glideModel = model
        val m = URL_WIDTH_PATTERN.matcher(glideModel)
        var bestBucket = 0
        if (m.find()) {
            val found = m.group(1)?.split("-")?.toTypedArray()
            val length = found?.size
            if (length != null && length > 0) {
                val intFound = IntArray(length)
                for (i in 0 until length) {
                    intFound[i] = found[i].toInt()
                }
                bestBucket = Utils.nearestNumber(width, intFound)
            }
            if (bestBucket > 0) {
                glideModel = m.replaceFirst("w$bestBucket")
            }
        }
        return glideModel
    }

    override fun handles(s: String): Boolean {
        return true
    }

    companion object {
        val URL_WIDTH_PATTERN = Pattern.compile("__w-((?:-?\\d+)+)__")
    }
}

Let’s see what’s happening in this class

  1. When glide receives a request to load an image, first it will call the getUrl method of this class with URL, image width and height. The loader can return the updated URL if it detects that the server supports responsive images.
  2. We will check for responsive support with URL_WIDTH_PATTERN.matcher(glideModel)
  3. If responsive images are available, we will get the list and will iterate through the list to find the best bucket size for the ImageView
  4. If bucket size is found, we will update the URL to replace variable size URL with that particular bucket.

Yey! We are done with the responsive image implementation using Glide library. Now images will be loaded very efficiently and users will love you for making the app faster and smoother.

Conclusion 

That’s it for today. Even though the implementation is provided only for android, a similar approach can be used for all platforms like web, iOS, flutter etc.

I will explore how it can be done with Jetpack compose in a separate post later. Please let me know your thoughts and feedback on responsive image loading.

Useful Articles


jimmy image
Jimmy Sanghani
Jimmy Sanghani is a tech nomad and cofounder at Canopas helping businesses use new age leverage - Code and Media - to grow their revenue exponentially. With over a decade of experience in both web and mobile app development, he has helped 100+ clients transform their visions into impactful digital solutions. With his team, he's helping clients navigate the digital landscape and achieve their objectives, one successful project at a time.


jimmy image
Jimmy Sanghani
Jimmy Sanghani is a tech nomad and cofounder at Canopas helping businesses use new age leverage - Code and Media - to grow their revenue exponentially. With over a decade of experience in both web and mobile app development, he has helped 100+ clients transform their visions into impactful digital solutions. With his team, he's helping clients navigate the digital landscape and achieve their objectives, one successful project at a time.

contact-footer
Say Hello!
footer
Subscribe Here!
Follow us on
2024 Canopas Software LLP. All rights reserved.