Glide — How to Ignore URL Query Parameters In Cache Lookup

Glide has a fairly complex caching system, which we've described in the tutorials on caching basics and best cache preferences. Vijoy consequently asked, if it's possible that Glide ignores (some) query parameters during the cache lookup. For example, if you have to send an access token, which changes every few minutes, with the image, the disk cache will be virtually useless. In this tutorial you'll learn how you can ignore query parameters and increase the effectiveness of Glide's disk cache.

Glide Series Overview

Issues With Dynamic URLs

If you load images from an Internet location, Glide will differentiate the cache for each image by the passed URL. For example, if you're loading https://futurestud.io/images/futurestudio-logo-transparent.png, Glide will put the resulting image with the full URL as a key into the disk cache. If you're reloading our logo on a different screen, it can re-use it from the disk cache. In summary, the key to resources for Glide's disk cache is the passed URL. Unfortunately, it gets complicated when the URLs are dynamic, but actually describe the same resource.

It's time to look at a small demo. Let's assume you're passing an analytics parameter along with your request:

http://www.placehold.it/500x500?source=feed  
http://www.placehold.it/500x500?source=detail  

In both versions, you're loading the same image. The source query parameter just tells the server from which view you're loading the image, which serves a purely analytical purpose. The image is the exact same. As mentioned before, Glide would see those as different resources, since the full URL is not identical. Both images would create a loading process over your user's network and fill up the disk cache. In the next section, we'll show you an approach how you can avoid both.

Implementation of GlideUrl

In short, you need to separate the base URL, which describes the resource, with optional parameters, which don't have any effect on the image. For the example above, the http://www.placehold.it/500x500 is the base URL, while ?source=feed is irrelevant for the content of the image.

LiHanGuang provided the foundation for our solution. Instead of simply passing a String as the resource URL, we're extending the GlideUrl class. This allows us to separate the base URL and the query parameters.

Simple Version for One Parameter

public class GlideUrlWithQueryParameter extends GlideUrl {  
    private String mSourceUrl;

    public GlideUrlWithQueryParameter(String baseUrl, String key, String value) {
        super(buildUrl(baseUrl, key, value));

        mSourceUrl = baseUrl;
    }

    private static String buildUrl(String baseUrl, String key, String value) {
        StringBuilder stringBuilder = new StringBuilder(baseUrl);

        if (stringBuilder.toString().contains("?")) {
            stringBuilder.append("&");
        }
        else {
            stringBuilder.append("?");
        }

        stringBuilder.append(key);
        stringBuilder.append("=");
        stringBuilder.append(value);

        return stringBuilder.toString();
    }

    @Override
    public String getCacheKey() {
        return mSourceUrl;
    }

    @Override
    public String toString() {
        return super.getCacheKey();
    }
}

The code above shows you a few interesting implementation details. The constructor does not take a single String; it asks for the base URL, the query parameter key and value. The critical part is that we're returning just the mSourceUrl, which is without the query parameters, as cache key at getCacheKey(). All other images, which we'll load in the future with the same base URL, but different query parameters, will hit the correct cache object.

If you want to load an image with the GlideUrlWithQueryParameter class from above, you'll just need to change one line in your Glide call:

Glide 4.x

GlideApp  
    .with(context)
      .load(new GlideUrlWithQueryParameter("http://placehold.it/500x500", "source", "feed"))
      .into(imageView1);

Glide 3.x

Glide  
    .with(context)
    .load(new GlideUrlWithQueryParameter("http://placehold.it/500x500", "source", "feed"))
    .into(imageView1);

The call is a little less convenient than just throwing a full URL as a String at it, but your user will thank you for the saved bandwidth and disk space. This works fantastic if you only have a single parameter. However, even if you need more than one, we got you covered.

Advanced Version for Multiple Parameters

We've extended the GlideUrlWithQueryParameter class with a second constructor. Instead of two separated Strings for the query parameter key and query parameter value, we're asking for a Java map. This gives you the possibility of one, or multiple, query parameters for a single image.

public class GlideUrlWithQueryParameter extends GlideUrl {  
    private String mSourceUrl;

    public GlideUrlWithQueryParameter(String baseUrl, String key, String value) {
        super(buildUrl(baseUrl, key, value));

        mSourceUrl = baseUrl;
    }

    public GlideUrlWithQueryParameter(String baseUrl, Map<String, Object> queryParams) {
        super(buildUrl(baseUrl, queryParams));

        mSourceUrl = baseUrl;
    }

    private static String buildUrl(String baseUrl, String key, String value) {
        StringBuilder stringBuilder = new StringBuilder(baseUrl);

        if (stringBuilder.toString().contains("?")) {
            stringBuilder.append("&");
        }
        else {
            stringBuilder.append("?");
        }

        stringBuilder.append(key);
        stringBuilder.append("=");
        stringBuilder.append(value);

        return stringBuilder.toString();
    }

    private static String buildUrl(String baseUrl, Map<String, Object> queryParams) {
        StringBuilder stringBuilder = new StringBuilder(baseUrl);

        for (Map.Entry<String, Object> entry : queryParams.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            if (stringBuilder.toString().contains("?")) {
                stringBuilder.append("&");
            }
            else {
                stringBuilder.append("?");
            }

            stringBuilder.append(key);
            stringBuilder.append("=");
            stringBuilder.append(value);
        }

        return stringBuilder.toString();
    }

    @Override
    public String getCacheKey() {
        return mSourceUrl;
    }

    @Override
    public String toString() {
        return super.getCacheKey();
    }
}

The usage requires a little preparation now:

Glide 4.x

HashMap<String, Object> queryParams = new HashMap<>();  
queryParams.put("source", "feed");  
queryParams.put("access", "mysecrettoken");

GlideApp  
    .with(context)
      .load(new GlideUrlWithQueryParameter("http://placehold.it/500x500", queryParams))
    .into(imageView2);

Glide 3.x

HashMap<String, Object> queryParams = new HashMap<>();  
queryParams.put("source", "feed");  
queryParams.put("access", "mysecrettoken");

Glide  
    .with(context)
    .load(new GlideUrlWithQueryParameter("http://placehold.it/500x500", queryParams))
    .into(imageView2);

Here you can see our example from the introduction in action. Additionally to our source info we're also passing an access token, that allows us to load the image.

Beware of Potential Bugs

Just as a reminder, make sure you pass the correct base URL. If a query parameter influences the image resource, you've to include it into the base URL!

GlideApp  
    .with(context)
    .load(new GlideUrlWithQueryParameter("http://futurestud.io/404.png?w=500&h=500", "source", "feed"))
    .into(imageView1);

See how we included the w=500&h=500 into the base URL? Otherwise Glide will take images from the cache, even if they don't have the correct size. This will lead to incorrectly sized images and can break your UI. Be careful!

Outlook

In this tutorial we've shown you a practical solution to the problem of dynamic URLs with query parameters for static images. If you know that the image is the same, even if the query parameters change over time, you can use the solution from this tutorial to improve the user experience of your app.

We appreciate feedback and love to help you if there’s a question in your mind. Let us know in the comments or on twitter @futurestud_io.

Make it rock & enjoy coding!

Explore the Library

Find interesting tutorials and solutions for your problems.