Cache Optimization Mechanisms in Glide
Image downloading consumes significant resources, making caching a critical component of image loading frameworks. Glide implements a sophisticated multi-tier caching system:
| Cache Type | Implementation | Description |
|---|---|---|
| Active Cache | ActiveResources | Stores currently used images retrieved from memory cache |
| Memory Cache | LruResourceCache | Caches recently parsed and loaded images in memory |
| Disk Cache - Resource | DiskLruCacheWrapper | Stores decoded images on disk |
| Disk Cache - Raw Data | DiskLruCacheWrapper | Caches original network response data on disk |
Memory Cache Architecture
Glide employs two complementary memory caching strategies by default (configurable via skipMemoryCache):
- ActiveResources: Weak-referenced HashMap protecting in-use images from LruCache eviction
- LruResourceCache: Standard LRU implementation for recently accessed images
Cache retrieval flow:
- Generate cache key from image URL, dimensions, transformations, and signtaure
- First attempt: Check ActiveResources cache (miss if first load)
- Second attempt: Check LruResourceCache, moving found items to ActiveResources
- Subsequent loads: Hit ActiveResources cache directly
- Resource cleanup: Move from ActiveResources to LruResourceCache when reference count reaches zero
Dual cache rationale: LRU algorithms遍历无序Sets during trim operations, potentially removing actively used images. The weak-referenced ActiveResources protects currently displayed images from premature eviction while leveraging LRU benefits for less frequently accessed content.
Disk Cache Strategies
Glide provides multiple disk caching strategies:
DiskCacheStrategy.NONE: No disk cachingDiskCacheStrategy.RESOURCE: Caches transformed/processed imagesDiskCacheStrategy.DATA: Caches original pre-transformation dataDiskCacheStrategy.ALL: Uses both DATA and RESOURCE caching for remote dataDiskCacheStrategy.AUTOMATIC: Intelligent strategy selection based on data source
Dual disk cache rationale: Different cache keys enable efficient handling of various display scenarios. RESOURCE caching avoids redundant transformasions for identical output requirements, while DATA caching prevents redundant downloads for different transformation needs.
// Resource cache key includes transformation parameters
ResourceCacheKey key = new ResourceCacheKey(
pool, sourceId, signature, width, height,
transformation, resourceClass, options
);
// Data cache key uses original source signature
DataCacheKey dataKey = new DataCacheKey(loadData.sourceKey, signature);
Memory Optimization Techniques
Glide implements several Bitmap-specific memory optimizations:
Dimensional Optimization
Uses inSampleSize to scale images appropriately for target view dimensions, reducing memory footprint significantly (e.g., 4x sample size reduces memory usage to 1/16 of original).
int widthRatio = sourceWidth / targetWidth;
int heightRatio = sourceHeight / targetHeight;
int sampleSize = (rounding == MEMORY)
? Math.max(widthRatio, heightRatio)
: Math.min(widthRatio, heightRatio);
sampleSize = Math.max(1, Integer.highestOneBit(sampleSize));
options.inSampleSize = sampleSize;
Bitmap Format Optimization
Different pixel formats offer memory/quality tradeoffs:
ALPHA_8: 1 byte/pixel (no color)RGB_565: 2 bytes/pixel (reduced color fidelity)ARGB_8888: 4 bytes/pixel (default, high quality)RGBA_F16: 8 bytes/pixel (wide gamut/HDR)
Note: Glide 4.0+ defaults to ARGB_8888 instead of previous RGB_565 default.
Memory Reuse via BitmapPool
Leverages inBitmap and Bitmap pooling to prevent memory fragmentation from frequent Bitmap allocation/deallocation.
private static void configureBitmapReuse(
BitmapFactory.Options options,
BitmapPool pool,
int width,
int height
) {
Bitmap.Config config = options.inPreferredConfig;
options.inBitmap = pool.getDirty(width, height, config);
}
Lifecycle Management
Glide automatically manages request lifecycle through Fragment integration:
- Fragment attachment:
Glide.with()creates/attaches a RequestManagerFragment to the activity - Lifecycle binding: RequestManager observes fragment lifecycle events
- Automatic cleanup: Requests are cancelled and resources released on fragment destruction
public RequestManager obtain(Activity activity) {
FragmentManager fm = activity.getFragmentManager();
RequestManagerFragment fragment = getRequestManagerFragment(fm);
RequestManager manager = fragment.getRequestManager();
if (manager == null) {
manager = factory.build(glide, fragment.getLifecycle(), context);
fragment.setRequestManager(manager);
}
return manager;
}