目录
4. 磁盘缓存实现(DiskLruCacheWrapper)
一、核心工作原理与源码分析
Glide 的设计围绕高效加载、生命周期管理和多层缓存展开,其核心流程如下:
1. 初始化与生命周期绑定
-
单例初始化:
通过Glide.with(context)
触发初始化(仅首次调用时创建实例)。// Glide.java public static RequestManager with(Context context) { return getRetriever(context).get(context); }
-
内部通过
GlideBuilder
构建线程池、内存缓存等组件。
-
-
生命周期管理:
Glide 通过向 Activity/Fragment 添加一个隐藏的 SupportRequestManagerFragment 监听生命周期。// RequestManagerRetriever.java private RequestManager fragmentGet(Context context, FragmentManager fm) { SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm); RequestManager requestManager = current.getRequestManager(); if (requestManager == null) { requestManager = new RequestManager(...); current.setRequestManager(requestManager); } return requestManager; }
-
当 Activity 销毁时,自动取消未完成请求,避免内存泄漏。
-
2. 图片加载流程(源码核心)
调用 Glide.with().load().into()
的完整流程:
-
Engine.load():协调缓存与加载任务。
// Engine.java public <R> LoadStatus load(...) { // 1. 检查活动资源(ActiveResources) EngineResource<?> active = loadFromActiveResources(key); if (active != null) return new LoadStatus(cb, active); // 2. 检查内存缓存(Memory Cache) EngineResource<?> cached = loadFromCache(key); if (cached != null) return new LoadStatus(cb, cached); // 3. 创建新任务(DecodeJob) EngineJob<R> engineJob = engineJobFactory.build(...); DecodeJob<R> decodeJob = decodeJobFactory.build(...); engineJob.start(decodeJob); }
-
DecodeJob.run():执行解码任务。
-
从磁盘缓存或网络获取数据,解码为 Bitmap。
// DecodeJob.java public void run() { DataFetcher<?> fetcher = currentGenerator.getNextFetcher(); fetcher.loadData(..., new DataCallback<Object>() { @Override public void onDataReady(Object data) { decodeFromRetrievedData(); // 解码数据 } }); }
-
-
Target.onResourceReady():将结果回调到主线程更新 ImageView。
二、缓存工作机制与 LRU 算法原理
1. 三级缓存架构
Glide 采用三级缓存策略,优先级从高到低:
缓存层级 | 实现方式 | 作用场景 |
---|---|---|
活动资源 | WeakReference 弱引用集合 | 正在使用的资源(如当前显示的图片) |
内存缓存 | LruResourceCache (LRU 算法) | 高频访问的已解码资源 |
磁盘缓存 | DiskLruCacheWrapper (LRU 算法) | 持久化存储原始或处理后的数据 |
2. LRU 算法原理
LRU(Least Recently Used) 是一种基于时间局部性的缓存淘汰策略,优先淘汰最久未访问的数据。
-
数据结构:
-
双向链表:维护访问顺序,最近访问的节点靠近头部,最久未访问的靠近尾部。
-
哈希表:以键(Key)快速定位链表节点。
-
-
操作流程:
-
访问数据:
-
命中缓存 → 移动节点到链表头部。
-
未命中 → 加载数据后插入头部。
-
-
淘汰数据:缓存满时删除尾部节点。
-
3. 内存缓存实现(LruResourceCache)
-
缓存大小:默认应用可用内存的 1/8(可配置)。
// MemorySizeCalculator.java static int getMaxCacheSize(ActivityManager activityManager) { return activityManager.getMemoryClass() * 1024 * 1024 / 8; }
-
源码关键逻辑:
// LruCache.java(Android SDK) public class LruCache<K, V> { public final V get(K key) { synchronized (this) { V mapValue = map.get(key); if (mapValue != null) { hitCount++; return mapValue; } missCount++; } V createdValue = create(key); synchronized (this) { createCount++; if (createdValue != null) { size += safeSizeOf(key, createdValue); map.put(key, createdValue); trimToSize(maxSize); // 触发淘汰机制 } return createdValue; } } public void trimToSize(int maxSize) { while (size > maxSize) { Map.Entry<K, V> toEvict = map.entrySet().iterator().next(); remove(toEvict.getKey()); // 删除尾部数据 } } }
4. 磁盘缓存实现(DiskLruCacheWrapper)
-
文件结构:
-
日志文件(journal):记录缓存操作(如访问、添加、删除)。
-
数据文件:每个缓存条目对应
.0
(元数据)和.1
(实际数据)文件。
-
-
LRU 维护:
-
访问数据时更新日志时间戳。
-
缓存满时按 LRU 顺序删除旧文件。
-
5. 缓存流程图
加载请求 → 检查 Active Resources → 命中则返回
↓ 未命中
检查 Memory Cache → 命中则移入 Active Resources 后返回
↓ 未命中
检查 Disk Cache → 命中则解码后缓存到 Memory
↓ 未命中
从网络/本地加载 → 解码 → 缓存到 Disk 和 Memory → 加入 Active Resources
三、使用注意事项
1. 内存优化
-
限制图片尺寸:避免加载超大图。
Glide.with(context) .load(url) .override(500, 500) // 指定加载分辨率 .into(imageView);
-
慎用自定义变换:如圆形裁剪可能导致内存激增。
2. 缓存配置
-
策略选择:
.diskCacheStrategy(DiskCacheStrategy.DATA) // 仅缓存原始数据 .skipMemoryCache(true) // 跳过内存缓存
-
手动清理:
Glide.get(context).clearMemory(); // 清理内存缓存(主线程) new Thread(() -> Glide.get(context).clearDiskCache()).start(); // 清理磁盘缓存
3. 生命周期与泄漏预防
-
禁止使用 ApplicationContext:失去生命周期管理可能导致泄漏。
-
列表复用问题:在
RecyclerView
中需手动清理旧请求:Glide.with(context).clear(holder.imageView); // 在 onBindViewHolder 中调用
4. 网络层优化
-
集成 OkHttp:提升网络加载效率。
implementation 'com.github.bumptech.glide:okhttp3-integration:4.12.0'
5. 调试与监控
-
开启详细日志:
Glide.with(context).setLogLevel(Log.VERBOSE);
-
内存监控:使用 Android Profiler 观察 Bitmap 内存变化。
四、总结
Glide 通过三级缓存与LRU 算法实现高效图片加载,源码中 LruResourceCache
和 DiskLruCacheWrapper
分别管理内存与磁盘缓存。实际开发中需注意内存优化、生命周期绑定及缓存策略配置,避免常见性能问题。LRU 算法通过双向链表与哈希表的高效协作,结合时间局部性原理,显著提升了缓存命中率,是 Glide 高性能的核心保障。
推荐: