Glide 核心原理
问题
Glide 的三级缓存和生命周期绑定是如何实现的?
答案
Glide 架构
三级缓存
| 层级 | 类型 | 实现 | 说明 |
|---|---|---|---|
| L1 | Active Resources | WeakReference HashMap | 正在显示的图片 |
| L2 | Memory Cache | LruCache | 未显示但常用的图片 |
| L3 | Disk Cache | DiskLruCache | 原始图片 + 转换后的图片 |
Active Resources 的设计:正在被 View 引用的图片用弱引用持有,不占用 LruCache 配额。当 View 不再引用时,图片从 Active 移入 LruCache。
生命周期绑定
Glide 向 Activity/Fragment 添加一个不可见的 Fragment(RequestManagerFragment),通过它监听宿主的生命周期,在 onStop 暂停加载、onDestroy 取消加载并清理资源。
常用配置
Glide.with(context)
.load(url)
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.transform(CenterCrop(), RoundedCorners(16))
.override(300, 300) // 指定加载尺寸,减少内存
.into(imageView)
自定义 AppGlideModule
@GlideModule
class MyGlideModule : AppGlideModule() {
override fun applyOptions(context: Context, builder: GlideBuilder) {
// 自定义内存缓存大小
builder.setMemoryCache(LruResourceCache(20 * 1024 * 1024)) // 20MB
// 自定义磁盘缓存
builder.setDiskCache(InternalCacheDiskCacheFactory(context, 100 * 1024 * 1024))
}
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
// 替换网络层为 OkHttp
registry.replace(GlideUrl::class.java, InputStream::class.java,
OkHttpUrlLoader.Factory())
}
}
常见面试问题
Q1: Glide 内存缓存的 key 是什么?
答案:
Glide 的缓存 key 由多个要素组成:URL、宽高、变换(Transform)、签名(Signature)等。这意味着同一张图片不同尺寸会缓存多份。通过 override() 统一尺寸可以提高缓存命中率。
Q2: DiskCacheStrategy 各选项的区别?
答案:
| 策略 | 缓存原图 | 缓存转换后 | 说明 |
|---|---|---|---|
NONE | ❌ | ❌ | 不缓存 |
DATA | ✅ | ❌ | 只缓存原始数据 |
RESOURCE | ❌ | ✅ | 只缓存转换后 |
ALL | ✅ | ✅ | 都缓存 |
AUTOMATIC | 根据策略决定 | 根据策略决定 | 默认,智能判断 |
Q3: Glide 如何避免图片错位?
答案:
每次调用 into(imageView) 时,Glide 会为该 ImageView 生成一个 Target。如果 ImageView 被复用(如 RecyclerView),新的 into() 调用会先取消之前 Target 的请求,再发起新请求。通过 View.setTag() 绑定当前请求,确保图片加载完成时只有最新请求的结果会被设置到 ImageView 上。