Glide makes loading images in your Android app quite efficient. Powerful caches avoid loading images over the (mobile) network as much as possible. However, that's not always feasible. Glide has to load images from the Internet when they're not in one of the caches yet.
Loading images over the network always hold a special tradeoff: quality or speed? Images in a larger resolution will need more bandwidth and a longer loading time. This is problematic because mobile devices can be on a slow connection. In today's tutorial, we'll show you how you can deal with this challenge.
Glide Series Overview
Why Load Different Versions Depending on the Connection?
As mentioned in the introduction, when the user is on a slow mobile connection your super crispy images will take forever to load. Thus, it's better to have an image in mediocre quality quickly than no image for a long time and consuming the user's bandwidth. We've shown you Glide thumbnails to deal with the time delay, but this will still bottle up the slow mobile network.
Luckily, Android allows you to get information about the user's connection and improve loading images depending on the network.
Check Network Connection
A simple version, which we'll use for the rest of this tutorial, is to check if the device is connected to WiFi. This doesn't guarantee an excellent connection, because some free public WiFi spots are significantly worse than a decent mobile connection. Nevertheless, this is generally a good heuristic:
private boolean deviceOnWifi() {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return networkInfo.isConnected();
}
If you want to use the snippet, you'll need to add a permission to the AndroidManifest.xml
:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
If you're interested in more detailed network connection info, you should check out Facebook's connection class.
Use Network Info
So let's put our new knowledge about the device into use. If the user is on WiFi, we're going to load an image in 750x750
resolution. Otherwise we'll only load a 100x100
image:
Glide 4.x
RequestManager requestManager = GlideApp.with(context);
RequestBuilder<Drawable> request;
// if you need transformations or other options specific for the load, chain them here
if (deviceOnWifi()) {
request = requestManager.load("http://www.placehold.it/750x750");
}
else {
request = requestManager.load("http://www.placehold.it/100x100");
}
request.into(imageView1);
Glide 3.x
RequestManager requestManager = Glide.with(context);
DrawableTypeRequest<String> request;
// if you need transformations or other options specific for the load, chain them here
if (deviceOnWifi()) {
request = requestManager.load("http://www.placehold.it/750x750");
}
else {
request = requestManager.load("http://www.placehold.it/100x100");
}
request.into(imageView1);
Of course, you can only use this approach if you can access your images in different resolutions. You might want to adjust the image sizes depending on your app as well.
This approach has one fatal flaw though. If the app loaded the high-quality image in the past and still has it in the disk cache, it'll load the low-quality image when the user is on a mobile connection. In the next section, we'll show you how to increase the image quality and save the user's mobile data.
Consider Cached Images
Unfortunately, Glide 3.x does not have a way to check if an image is in the disk cache. Luckily, there is a way around it. The following snippet for Glide 3.x is based on Róbert's suggestion.
The idea is to load the high-quality version when you're on WiFi. When the user is on a mobile connection, we'll try to request the high-quality image, but only if it's available in the cache by using Robert's snipet for Glide 3.x, and the .onlyRetrieveFromCache(true)
method for Glide 4.x. If the image is in the disk cache, it'll still get delivered. Otherwise, we'll load the low-quality image via the thumbnail
option:
Glide 4.x
// if you need transformations or other options specific for the load, chain them here
if (deviceOnWifi()) {
GlideApp
.with(context)
.load("http://www.placehold.it/750x750")
.into(imageView1);
}
else {
GlideApp
.with(context)
.load("http://www.placehold.it/750x750")
.onlyRetrieveFromCache(true)
.thumbnail(
GlideApp
.with(context)
.load("http://www.placehold.it/100x100")
)
.into(imageView1);
}
Glide 3.x
// if you need transformations or other options specific for the load, chain them here
if (deviceOnWifi()) {
Glide
.with(context)
.load("http://www.placehold.it/750x750")
.into(imageView1);
}
else {
Glide
.with(context)
.using(new NetworkDisablingLoader())
.load("http://www.placehold.it/750x750")
.thumbnail(
Glide
.with(context)
.load("http://www.placehold.it/100x100")
)
.into(imageView1);
}
In Glide 3.x you'll need the NetworkDisablingLoader
class, which you can find in Róbert's comment as well:
class NetworkDisablingLoader implements StreamModelLoader<String> {
@Override public DataFetcher<InputStream> getResourceFetcher(final String model, int width, int height) {
return new DataFetcher<InputStream>() {
@Override public InputStream loadData(Priority priority) throws Exception {
throw new IOException("Forced Glide network failure");
}
@Override public void cleanup() { }
@Override public String getId() { return model; }
@Override public void cancel() { }
};
}
}
Overall, this results in a good user experience. You're always loading images fairly quickly, using the cache (if possible) and use up as little mobile data as necessary.
Outlook
In this tutorial we've made you aware of the challenges of loading images on different Internet connections. The quality of WiFi connections and mobile data is vastly different and we've shown you a way of optimizing image loading for either scenario.
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!