Caching Images with Glide in Android
Images can make an Android app feel polished, but downloading every bitmap from a server wastes mobile data, delays screen rendering and increases battery use. Image caching stores reusable copies in memory or on disk, allowing later requests to complete much faster.
Glide is a popular Android image-loading library that handles downloading, decoding, resizing and caching for you. It works well with ImageView, RecyclerView and other common UI components, making it suitable for small practice apps and production projects.
Caching is especially useful for Australian users who may switch between fast home Wi-Fi in Sydney or Melbourne and limited mobile coverage while travelling through regional areas. A sensible cache policy can reduce data usage on prepaid plans and make image-heavy screens more responsive during a daily commute.
This tutorial uses Glide with Java examples, although the same API can be called from Kotlin. The examples cover installation, image loading, memory and disk cache behaviour, list performance and cache invalidation.
Adding Glide To An Android Project
Add the Glide dependency to the app-level build.gradle file. Version 4.16.0 is a stable example, but check the current release when starting a new project.
dependencies {
implementation 'com.github.bumptech.glide:glide:4.16.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0'
}
Sync the project, then add an ImageView to a layout. Glide can load a remote URL, a drawable resource, a local file or a content URI. It automatically creates a request suitable for the target view.
ImageView productImage = findViewById(R.id.productImage);
Glide.with(this)
.load("https://example.com/images/laptop.jpg")
.placeholder(R.drawable.image_placeholder)
.error(R.drawable.image_error)
.into(productImage);
The placeholder() drawable appears while the request is running, while error() is displayed if the URL cannot be downloaded or decoded. Use an Activity, Fragment or View context with Glide.with() so Glide can pause and cancel requests when the related screen is no longer active.
How Glide Stores Cached Images
Glide uses two main cache levels. The memory cache keeps recently used resources in RAM, which is extremely fast. The resource may already be decoded into a form suitable for the ImageView, so displaying it again avoids both network access and much of the decoding work.
The disk cache stores downloaded or transformed image data in the app’s private cache directory. It survives normal Activity recreation and is usually available when the user opens the app again. Android can remove cache files when storage is needed, so a cache should improve performance without being treated as permanent storage.
Glide also considers the requested image size and transformation when creating cache keys. A 200-pixel thumbnail and a full-size detail image may therefore occupy different entries. Calling override() can prevent unnecessarily large bitmaps from being decoded for small views.
Glide.with(this)
.load(imageUrl)
.override(400, 300)
.centerCrop()
.into(productImage);
Selecting A Strategy For Different Images
The default Glide behaviour is a useful starting point, but the best disk cache strategy depends on where the image comes from and how it will be used. Network images commonly benefit from caching the original data and the transformed result, while generated images may need a different approach.
| Strategy | Stores | Suitable use | Trade-off |
|---|---|---|---|
AUTOMATIC |
Chooses an efficient approach based on the data source | Most remote image requests | Less control over exact cache behaviour |
DATA |
Original downloaded data | Repeated transformations of the same network file | Transformation work may happen again |
RESOURCE |
Resized or transformed output | Images whose displayed form rarely changes | A new size or transformation needs another entry |
ALL |
Source data and transformed resource | Frequently reused remote images | Uses more disk space |
NONE |
No disk cache | One-time or sensitive content | Repeated requests use the network again |
For a standard product catalogue, AUTOMATIC is usually appropriate. A thumbnail list can use a fixed size and centerCrop(), while a detail screen can request a larger version. Avoid using ALL everywhere without checking storage usage, especially in apps with many high-resolution images.
Glide.with(this)
.load(product.getImageUrl())
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
.placeholder(R.drawable.product_placeholder)
.into(holder.imageView);
A useful policy for Australian shopping or news applications is to cache ordinary public images, but be more careful with account-related documents or temporary uploads. The Australian Privacy Act and the Australian Privacy Principles encourage organisations to handle personal information securely and retain it only when required. A private image should not be treated like a public product thumbnail.
Improving RecyclerView Image Performance
Glide works particularly well inside a RecyclerView because it manages request cancellation when rows are recycled. In an adapter, always bind the current URL and clear the ImageView when there is no valid image. This avoids showing an old row’s bitmap in a newly reused row.
@Override
public void onBindViewHolder(@NonNull ProductViewHolder holder, int position) {
Product product = products.get(position);
Glide.with(holder.itemView)
.load(product.getImageUrl())
.placeholder(R.drawable.product_placeholder)
.error(R.drawable.image_error)
.override(240, 240)
.centerCrop()
.into(holder.imageView);
}
Use appropriately sized server images where possible. Downloading a four-megapixel photograph for a small 240dp list item increases transfer time, decoding cost and cache consumption. This matters for users browsing on mobile data in outer suburbs or regional areas, where network speed and data allowances may vary.
For long lists, stable item layouts and consistent image dimensions reduce visual movement as requests finish. A placeholder with the same aspect ratio as the final bitmap also makes scrolling feel smoother. Glide’s memory cache can then reuse images as users scroll back to earlier products.
Practical Checks For Fast Lists
- Keep thumbnail dimensions consistent across RecyclerView rows.
- Use
override()when the server cannot provide smaller images. - Add a meaningful placeholder and error drawable.
- Load images from a stable URL rather than a changing temporary link.
Refreshing And Clearing Cached Content
A URL alone may not change when the image on the server changes. Glide will continue returning the cached version until its cache entry is replaced or invalidated. This is common when a user updates a profile picture but the application keeps displaying the previous file.
The cleanest solution is cache busting with a version value. Add a timestamp, revision number or server-provided content hash to the request signature. Glide then treats the new signature as a different cache entry while preserving unrelated images.
ObjectKey versionKey = new ObjectKey(user.getAvatarVersion());
Glide.with(imageView)
.load(user.getAvatarUrl())
.signature(versionKey)
.placeholder(R.drawable.avatar_placeholder)
.circleCrop()
.into(imageView);
When a user signs out, clear only the relevant UI state where possible. Glide.clear(imageView) cancels the current request and releases the resource associated with that view. Clearing all memory or disk caches is an expensive operation and should generally be performed away from the main thread.
Glide.with(context).clear(imageView);
Do not use cache clearing as a routine fix for every loading problem. First verify the URL, network permission, server response, image format and lifecycle owner. Android apps distributed through the Australian market should also explain account and data handling clearly in their privacy information, particularly when images can identify a person.
Troubleshooting Common Glide Problems
A missing image may be caused by a network security restriction rather than a cache failure. Modern Android versions usually permit HTTPS traffic, while unencrypted HTTP may be blocked unless the application explicitly allows it. Prefer HTTPS for all remote image URLs, including development endpoints that are exposed beyond a local machine.
If images appear too large, use fitCenter() or centerCrop() according to the layout. fitCenter() displays the whole image inside the bounds, while centerCrop() fills the bounds and may trim the edges. Supplying an accurate ImageView size and a matching override() value reduces memory pressure.
Useful Debugging Checks
- Confirm
<uses-permission android:name="android.permission.INTERNET" />is in the manifest. - Test the image URL in a browser and inspect its HTTP status.
- Check whether the server returns a supported format such as JPEG, PNG or WebP.
- Review Logcat for Glide, decoding or cleartext-network errors.
Glide is designed to manage most cache details automatically, so application code should focus on predictable URLs, sensible dimensions and appropriate lifecycle usage. With those choices in place, cached images load quickly, repeated downloads fall, and image-heavy Android screens remain practical for users across Australia.