Caching
Caching in Glide
By default, Glide checks multiple layers of caches before starting a new request for an image:
- Active resources - Is this image displayed in another View right now?
- Memory cache - Was this image recently loaded and still in memory?
- Resource - Has this image been decoded, transformed, and written to the disk cache before?
- Data - Was the data this image was obtained from written to the disk cache before?
The first two steps check to see if the resource is in memory and if so, return the image immediately. The second two steps check to see if the image is on disk and return quickly, but asynchronously.
If all four steps fail to find the image, then Glide will go back to the original source to retrieve the data (the original File, Uri, Url etc).
For details on default sizes and locations of Glide’s caches or to configure those parameters, see the configuration page.
Cache Keys
In Glide 4, all cache keys contain at least two elements:
- The model the load is requested for (File, Uri, Url) (If you are using a custom model, it needs to correctly implements
hashCode()
andequals()
- An optional
Signature
In fact, the cache keys for steps 1-3 (Active resources, memory cache, resource disk cache) also include a number of other pieces of data including:
- The width and height
- The optional
Transformation
- Any added
Options
- The requested data type (Bitmap, GIF, etc)
The keys used for active resources and the memory cache also differ slightly from those used from the resource disk cache to accomodate in memory Options
like those thataffect the configuration of the Bitmap or other decode time only parameters.
To generate the name of disk cache keys on disk, the individual elements of the keys are hashed to create a single String key, which is then used as the file name in the disk cache.
Cache Configuration
Glide provides a number of options that allow you to choose how loads will interact with Glide’s caches on a per request basis.
Disk Cache Strategies
DiskCacheStrategy
can be applied with the diskCacheStrategy
method to an individual request. The available strategies allow you to prevent your load from using or writing to the disk cache or choose to cache only the unmodified original data backing your load, only the transformed thumbnail produced by your load, or both.
The default strategy, AUTOMATIC
, tries to use the optimal strategy for local and remote images. AUTOMATIC
will store only the unmodified data backing your load when you’re loading remote data (like from URLs) because downloading remote data is expensive compared to resizing data already on disk. For local data AUTOMATIC
will store the transformed thumbnail only because retrieving the original data is cheap if you need to generate a second thumbnail size or type.
To apply a DiskCacheStrategy
:
GlideApp.with(fragment)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(imageView);
Loading only from cache
In some circumstances you may want a load to fail if an image is not already in cache. To do so, you can use the onlyRetrieveFromCache
method on a per request basis:
GlideApp.with(fragment)
.load(url)
.onlyRetrieveFromCache(true)
.into(imageView);
If the image is found in the memory cache or in the disk cache, it will be loaded. Otherwise, if this option is set to true, the load will fail.
Skipping the cache.
If you’d like to make sure a particular request skips either the disk cache or the memory cache or both, Glide provides a few alternatives.
To skip the memory cache only, use skipMemoryCache()
:
GlideApp.with(fragment)
.load(url)
.skipMemoryCache(true)
.into(view);
To skip the disk cache only, use DiskCacheStrategy.NONE
:
GlideApp.with(fragment)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(view);
These options can be used together:
GlideApp.with(fragment)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(view);
In general you want to try to avoid skipping caches. It’s vastly faster to load an image from cache than it is to retrieve, decode, and transform it to create a new thumbnail.
If you’d just like to update the entry for an item in the cache, see the documentation on invalidation
below.
Implementation
If the available options aren’t sufficient for your needs, you can also write your own DiskCache
implementation. See the configuration page for details.
Cache Invalidation
Because disk cache are hashed keys, there is no good way to simply delete all of the cached files on disk that correspond to a particular url or file path. The problem would be simpler if you were only ever allowed to load or cache the original image, but since Glide also caches thumbnails and provides various transformations, each of which will result in a new File in the cache, tracking down and deleting every cached version of an image is difficult.
In practice, the best way to invalidate a cache file is to change your identifier when the content changes (url, uri, file path etc) when possible.
Custom Cache Invalidation
Since it’s often difficult or impossible to change identifiers, Glide also offers the signature()
API to mix in additional data that you control into your cache key. Signatures work well for media store content, as well as any content you can maintain some versioning metadata for.
- Media store content - For media store content, you can use Glide’s
MediaStoreSignature
class as your signature.MediaStoreSignature
allows you to mix the date modified time, mime type, and orientation of a media store item into the cache key. These three attributes reliably catch edits and updates allowing you to cache media store thumbs. - Files - You can use
ObjectKey
to mix in the File’s date modified time. - Urls - Although the best way to invalidate urls is to make sure the server changes the url and updates the client when the content at the url changes, you can also use
ObjectKey
to mix in arbitrary metadata (such as a version number) instead.
Passing in signatures to loads is simple:
GlideApp.with(yourFragment)
.load(yourFileDataModel)
.signature(new ObjectKey(yourVersionMetadata))
.into(yourImageView);
The media store signature is also straightforward data from the MediaStore:
GlideApp.with(fragment)
.load(mediaStoreUri)
.signature(new MediaStoreSignature(mimeType, dateModified, orientation))
.into(view);
You can also define your own signature by implementing the Key
interface. Be sure to implement equals()
, hashCode()
and the updateDiskCacheKey()
method:
public class IntegerVersionSignature implements Key {
private int currentVersion;
public IntegerVersionSignature(int currentVersion) {
this.currentVersion = currentVersion;
}
@Override
public boolean equals(Object o) {
if (o instanceof IntegerVersionSignature) {
IntegerVersionSignature other = (IntegerVersionSignature) o;
return currentVersion = other.currentVersion;
}
return false;
}
@Override
public int hashCode() {
return currentVersion;
}
@Override
public void updateDiskCacheKey(MessageDigest md) {
messageDigest.update(ByteBuffer.allocate(Integer.SIZE).putInt(signature).array());
}
}
Keep in mind that to avoid degrading performance, you will want to batch load any versioning metadata in the background so that it is available when you want to load your image.
If all else fails and you can neither change your identifier nor keep track of any reasonable version metadata, you can also disable disk caching entirely using diskCacheStrategy()
and DiskCacheStrategy.NONE
.
Resource Management
Glide’s disk and memory caches are LRU which means that they take increasingly more memory and/or disk space until they reach their limit at which point they will use at or near the limit continuously. For some added flexibility, Glide provides a few additional ways you can manage the resources your application uses.
Keep in mind that larger memory caches, bitmap pools and disk caches typically provide somewhat better performance, at least up to a point. If you change cache sizes, you should carefully measure performance before and after your changes to make sure the performance/size tradeoffs are reasonable.
Memory Cache
By default Glide’s memory cache and BitmapPool
respond to ComponentCallbacks2
and automatically evict their contents to varying degrees depending on the level the framework provides. As a result, you typically don’t need to try to dynamically monitor or clear your cache or BitmapPool
. However, should the need arise, Glide does provide a couple of manual options.
Permanent size changes
To change the amount of RAM available to Glide across your application, see the Configuration page.
Temporary size changes.
To temporarily allow Glide to use more or less memory in certain parts of your app, you can use setMemoryCategory
:
Glide.get(context).setMemoryCategory(MemoryCategory.LOW);
// Or:
Glide.get(context).setMemoryCategory(MemoryCategory.HIGH);
Make sure to reset the memory category back when you leave the memory or performance sensitive area of your app:
Glide.get(context).setMemoryCategory(MemoryCategory.NORMAL);
Clearing memory
To simply clear out Glide’s in memory cache and BitmapPool
, use clearMemory
:
// This method must be called on the main thread.
Glide.get(context).clearMemory();
Clearing all memory isn’t particularly efficient and should be avoided whenever possible to avoid jank and increased loading times.
Disk Cache
Glide provides only limited controls for the disk cache size at run time, but the size and configuration can be changed in an AppGlideModule
.
Permanent size changes
To change the amount of sdcard space available to Glide’s disk cache across your application, see the Configuration page.
Clearing the disk cache
To try to clear out all items in the disk cache, you can use clearDiskCache
:
new AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
// This method must be called on a background thread.
Glide.get(applicationContext).clearDiskCache();
return null;
}
}