A fast and efficient open source media management and image loading framework for Android that wraps media decoding, memory and disk caching, and resource pooling into a simple and easy to use interface.
—
Glide's sophisticated caching system provides multi-level caching with both memory and disk components, offering fine-grained control over cache behavior, sizing, and strategies. The system is built around the MemoryCache and DiskCache interfaces with configurable strategies through the DiskCacheStrategy enum and comprehensive cache management APIs.
The memory cache provides fast access to recently loaded images, keeping them in RAM for immediate display:
public interface MemoryCache {
/**
* Gets the current size of the cache in bytes
* @return Current cache size
*/
long getCurrentSize();
/**
* Gets the maximum size of the cache in bytes
* @return Maximum cache size
*/
long getMaxSize();
/**
* Sets a multiplier for the cache size
* @param multiplier Size multiplier (0.0-1.0)
*/
void setSizeMultiplier(float multiplier);
/**
* Stores a resource in the cache
* @param key The cache key
* @param resource The resource to cache
* @return Previous resource at key, or null
*/
Resource<?> put(Key key, Resource<?> resource);
/**
* Retrieves a resource from the cache
* @param key The cache key
* @return Cached resource or null
*/
Resource<?> remove(Key key);
/**
* Clears all entries from memory cache
*/
void clearMemory();
/**
* Trims memory cache to specified level
* @param level Trim level from ComponentCallbacks2
*/
void trimMemory(int level);
}The disk cache provides persistent storage for images across application restarts:
public interface DiskCache {
/**
* Writer interface for writing cache entries
*/
public interface Writer {
/**
* Writes data to the cache entry
* @param file The file to write to
* @return True if write successful
*/
boolean write(File file);
}
/**
* Factory interface for creating disk caches
*/
public interface Factory {
/**
* Default disk cache directory name
*/
String DEFAULT_DISK_CACHE_DIR = "image_manager_disk_cache";
/**
* Default disk cache size in bytes (250 MB)
*/
long DEFAULT_DISK_CACHE_SIZE = 250L * 1024 * 1024;
/**
* Creates a disk cache instance
* @return New DiskCache instance
*/
DiskCache build();
}
/**
* Retrieves a file from the cache
* @param key The cache key
* @return Cached file or null
*/
File get(Key key);
/**
* Stores data in the cache
* @param key The cache key
* @param writer Writer to create cache entry
*/
void put(Key key, Writer writer);
/**
* Removes entry from cache
* @param key The cache key
*/
void delete(Key key);
/**
* Clears all entries from disk cache
*/
void clear();
}Controls which versions of images are cached to disk:
public enum DiskCacheStrategy {
/**
* Caches all versions of images (original and transformed)
* Provides fastest loading but uses most disk space
*/
ALL,
/**
* Disables disk caching completely
* Saves disk space but requires re-downloading/processing
*/
NONE,
/**
* Caches only original source data
* Useful for images that are transformed differently
*/
DATA,
/**
* Caches only transformed/processed images
* Good for consistent transformations
*/
RESOURCE,
/**
* Intelligently chooses strategy based on image source
* Default strategy - caches remote images but not local
*/
AUTOMATIC;
/**
* Gets default strategy
*/
public static DiskCacheStrategy getDefault() {
return AUTOMATIC;
}
/**
* Checks if strategy caches original data
*/
public static boolean isDataCacheable(DiskCacheStrategy strategy) {
return strategy == ALL || strategy == DATA || strategy == AUTOMATIC;
}
/**
* Checks if strategy caches processed resources
*/
public static boolean isResourceCacheable(DiskCacheStrategy strategy) {
return strategy == ALL || strategy == RESOURCE || strategy == AUTOMATIC;
}
}The default memory cache implementation using Least Recently Used (LRU) eviction:
public class LruResourceCache implements MemoryCache {
private final long maxSize;
/**
* Creates LRU cache with specified size
* @param maxSize Maximum cache size in bytes
*/
public LruResourceCache(long maxSize) {
this.maxSize = maxSize;
}
@Override
public long getCurrentSize() {
// Implementation details
return 0;
}
@Override
public long getMaxSize() {
return maxSize;
}
@Override
public void setSizeMultiplier(float multiplier) {
// Implementation details
}
@Override
public Resource<?> put(Key key, Resource<?> resource) {
// Implementation details
return null;
}
@Override
public Resource<?> remove(Key key) {
// Implementation details
return null;
}
@Override
public void clearMemory() {
// Implementation details
}
@Override
public void trimMemory(int level) {
// Implementation details
}
/**
* Gets current number of entries
*/
public int getCurrentEntryCount() {
// Implementation details
return 0;
}
/**
* Gets eviction count since creation
*/
public long getEvictionCount() {
// Implementation details
return 0;
}
}Creates disk cache in internal app storage:
public class InternalCacheDiskCacheFactory implements DiskCache.Factory {
private final Context context;
private final String diskCacheName;
private final long diskCacheSize;
/**
* Creates internal cache factory with default settings
* @param context Application context
*/
public InternalCacheDiskCacheFactory(Context context) {
this(context, DEFAULT_DISK_CACHE_DIR, DEFAULT_DISK_CACHE_SIZE);
}
/**
* Creates internal cache factory with custom size
* @param context Application context
* @param diskCacheSize Cache size in bytes
*/
public InternalCacheDiskCacheFactory(Context context, long diskCacheSize) {
this(context, DEFAULT_DISK_CACHE_DIR, diskCacheSize);
}
/**
* Creates internal cache factory with all custom parameters
* @param context Application context
* @param diskCacheName Cache directory name
* @param diskCacheSize Cache size in bytes
*/
public InternalCacheDiskCacheFactory(Context context, String diskCacheName, long diskCacheSize) {
this.context = context;
this.diskCacheName = diskCacheName;
this.diskCacheSize = diskCacheSize;
}
@Override
public DiskCache build() {
// Implementation details
return null;
}
}Creates disk cache in external storage (SD card):
public class ExternalCacheDiskCacheFactory implements DiskCache.Factory {
private final Context context;
private final String diskCacheName;
private final long diskCacheSize;
/**
* Creates external cache factory with default settings
* @param context Application context
*/
public ExternalCacheDiskCacheFactory(Context context) {
this(context, DEFAULT_DISK_CACHE_DIR, DEFAULT_DISK_CACHE_SIZE);
}
/**
* Creates external cache factory with custom directory
* @param context Application context
* @param diskCacheFolder Custom cache directory name
* @param diskCacheSize Cache size in bytes
*/
public ExternalCacheDiskCacheFactory(Context context, String diskCacheFolder, long diskCacheSize) {
this.context = context;
this.diskCacheName = diskCacheFolder;
this.diskCacheSize = diskCacheSize;
}
/**
* Creates external cache factory with all custom parameters
* @param context Application context
* @param diskCacheName Cache directory name
* @param diskCacheSize Cache size in bytes
*/
public ExternalCacheDiskCacheFactory(Context context, String diskCacheName, long diskCacheSize) {
this.context = context;
this.diskCacheName = diskCacheName;
this.diskCacheSize = diskCacheSize;
}
@Override
public DiskCache build() {
// Implementation details
return null;
}
}Configure memory cache size and behavior:
public class CacheConfigurationActivity extends AppCompatActivity {
public void configureMemoryCache() {
// Get available memory
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
activityManager.getMemoryInfo(memoryInfo);
// Use 1/8th of available memory for image cache
long memoryCacheSize = memoryInfo.availMem / 8;
// Configure through GlideModule
class CustomGlideModule extends AppGlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
builder.setMemoryCache(new LruResourceCache(memoryCacheSize));
}
}
}
public void runtimeMemoryCacheControl() {
// Clear memory cache
Glide.get(this).clearMemory();
// Trim memory cache based on system state
Glide.get(this).trimMemory(ComponentCallbacks2.TRIM_MEMORY_MODERATE);
// Get memory cache size info
MemoryCache memoryCache = Glide.get(this).getMemoryCache();
long currentSize = memoryCache.getCurrentSize();
long maxSize = memoryCache.getMaxSize();
Log.d("Cache", "Memory cache: " + currentSize + " / " + maxSize + " bytes");
}
}Configure disk cache location and size:
public class DiskCacheConfigurationActivity extends AppCompatActivity {
public void configureDiskCache() {
class CustomGlideModule extends AppGlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
// Internal storage cache (100MB)
long internalCacheSize = 100 * 1024 * 1024L;
builder.setDiskCache(
new InternalCacheDiskCacheFactory(context, internalCacheSize)
);
// Or external storage cache (500MB)
long externalCacheSize = 500 * 1024 * 1024L;
builder.setDiskCache(
new ExternalCacheDiskCacheFactory(
context,
"my_app_cache",
externalCacheSize
)
);
}
}
}
public void clearDiskCache() {
// Must be called on background thread
new Thread(new Runnable() {
@Override
public void run() {
Glide.get(DiskCacheConfigurationActivity.this).clearDiskCache();
}
}).start();
}
}Control caching behavior for individual requests:
public class RequestCacheControlActivity extends AppCompatActivity {
public void demonstrateCacheStrategies() {
// Cache everything (original + transformed)
Glide.with(this)
.load(imageUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(imageView);
// Cache nothing to disk
Glide.with(this)
.load(imageUrl)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
// Cache only original data
Glide.with(this)
.load(imageUrl)
.diskCacheStrategy(DiskCacheStrategy.DATA)
.into(imageView);
// Cache only transformed result
Glide.with(this)
.load(imageUrl)
.transform(new CenterCrop())
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.into(imageView);
// Skip memory cache but use disk cache
Glide.with(this)
.load(imageUrl)
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(imageView);
}
public void cacheOnlyMode() {
// Load only from cache, don't fetch if not cached
Glide.with(this)
.load(imageUrl)
.onlyRetrieveFromCache(true)
.into(imageView);
}
}Create reusable cache configurations:
public class CachePresets {
// High performance: cache everything
public static final RequestOptions PERFORMANCE_FOCUSED = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.skipMemoryCache(false);
// Memory conscious: disk only
public static final RequestOptions MEMORY_CONSERVATIVE = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.skipMemoryCache(true);
// Bandwidth conscious: cache aggressively
public static final RequestOptions BANDWIDTH_CONSERVATIVE = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.onlyRetrieveFromCache(false);
// Testing/debugging: no caching
public static final RequestOptions NO_CACHE = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true);
}
public class CachePresetsActivity extends AppCompatActivity {
public void usePresets() {
// Apply performance preset
Glide.with(this)
.load(imageUrl)
.apply(CachePresets.PERFORMANCE_FOCUSED)
.into(imageView);
// Apply memory conservative preset
Glide.with(this)
.load(largeImageUrl)
.apply(CachePresets.MEMORY_CONSERVATIVE)
.into(imageView);
}
}Control cache behavior with custom cache keys:
public class CacheKeyManagementActivity extends AppCompatActivity {
public void customCacheKeys() {
// Object-based cache key
ObjectKey objectKey = new ObjectKey("user_profile_123");
Glide.with(this)
.load(profileImageUrl)
.signature(objectKey)
.into(profileImageView);
// MediaStore signature for local files
MediaStoreSignature mediaStoreSignature = new MediaStoreSignature(
"image/jpeg",
lastModified,
ExifInterface.ORIENTATION_NORMAL
);
Glide.with(this)
.load(localImageFile)
.signature(mediaStoreSignature)
.into(imageView);
// Application version signature
ApplicationVersionSignature appVersionSignature = ApplicationVersionSignature.obtain(this);
Glide.with(this)
.load(imageUrl)
.signature(appVersionSignature)
.into(imageView);
}
public void combinedSignatures() {
// Combine multiple signatures
List<Object> keyComponents = Arrays.asList(
"user_id_123",
"profile_version_5",
System.currentTimeMillis() / (1000 * 60 * 60) // Hour-based cache
);
ObjectKey combinedKey = new ObjectKey(keyComponents);
Glide.with(this)
.load(profileUrl)
.signature(combinedKey)
.into(profileView);
}
}Monitor and adjust cache sizes dynamically:
public class CacheMonitoringActivity extends AppCompatActivity {
public void monitorCacheUsage() {
MemoryCache memoryCache = Glide.get(this).getMemoryCache();
// Get current statistics
long currentSize = memoryCache.getCurrentSize();
long maxSize = memoryCache.getMaxSize();
int usagePercentage = (int) ((float) currentSize / maxSize * 100);
Log.d("CacheStats", "Memory cache usage: " + usagePercentage + "% (" + currentSize + " / " + maxSize + " bytes)");
// Adjust cache size based on memory pressure
if (usagePercentage > 90) {
memoryCache.setSizeMultiplier(0.8f); // Reduce by 20%
} else if (usagePercentage < 50) {
memoryCache.setSizeMultiplier(1.0f); // Full size
}
}
public void adaptiveCacheManagement() {
// Listen for memory pressure events
registerComponentCallbacks(new ComponentCallbacks2() {
@Override
public void onConfigurationChanged(Configuration newConfig) {}
@Override
public void onLowMemory() {
// Clear memory cache on low memory
Glide.get(CacheMonitoringActivity.this).clearMemory();
}
@Override
public void onTrimMemory(int level) {
// Trim cache based on system memory state
switch (level) {
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
Glide.get(CacheMonitoringActivity.this).clearMemory();
break;
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
Glide.get(CacheMonitoringActivity.this).trimMemory(level);
break;
}
}
});
}
}Preload images to warm up caches:
public class CacheWarmingActivity extends AppCompatActivity {
public void preloadImages() {
List<String> imagesToPreload = Arrays.asList(
"https://example.com/image1.jpg",
"https://example.com/image2.jpg",
"https://example.com/image3.jpg"
);
// Preload with specific dimensions
for (String url : imagesToPreload) {
Glide.with(this)
.load(url)
.preload(200, 200);
}
// Preload with default dimensions
Glide.with(this)
.load(heroImageUrl)
.preload();
}
public void intelligentPreloading() {
// Preload based on user behavior patterns
List<ImageData> upcomingImages = getUserBehaviorPredictor().getNextLikelyImages();
for (ImageData imageData : upcomingImages) {
RequestOptions options = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.DATA)
.priority(Priority.LOW); // Don't interfere with current requests
Glide.with(this)
.load(imageData.url)
.apply(options)
.preload(imageData.expectedWidth, imageData.expectedHeight);
}
}
}DiskCacheStrategy.AUTOMATIC for most use casespublic class CacheBestPractices {
// Optimal cache configuration for different scenarios
public static final RequestOptions PHOTO_GALLERY = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.RESOURCE) // Cache processed thumbnails
.priority(Priority.HIGH);
public static final RequestOptions USER_AVATARS = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.ALL) // Cache everything for profiles
.circleCrop() // Consistent transformation
.signature(new ObjectKey("avatar_v2")); // Version cache key
public static final RequestOptions LARGE_IMAGES = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.DATA) // Cache original, transform as needed
.format(DecodeFormat.PREFER_RGB_565); // Use less memory
public static final RequestOptions TEMPORARY_IMAGES = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.NONE) // Don't cache temporary content
.skipMemoryCache(true);
}This comprehensive caching system provides the flexibility and performance needed for efficient image loading while giving developers fine-grained control over memory and storage usage patterns.
Install with Tessl CLI
npx tessl i tessl/maven-com-github-bumptech-glide--glide