前言
Glide是一款专为Android设计的开源图片加载库。有以下特点:1.支持高效加载网络、本地及资源图片;2.具备良好的缓存策略及生命周期管理策略;3.提供了简易的API和强大的功能。本文将对其源码进行剖析。
基本使用
dependencies {
compile 'com.github.bumptech.glide:glide:3.7.0'
}
<uses-permission android:name="android.permission.INTERNET" />
java
// 基础用法:加载网络图片
Glide.with(context)
.load("https://ts1.tc.mm.bing.net/th/id/R-C.3a1b98d8aa749503cc2ff9c224bc8b40?rik=xxNkH0iChSUYqg&riu=http%3a%2f%2fd.ifengimg.com%2fq100%2fimg1.ugc.ifeng.com%2fnewugc%2f20190119%2f10%2fwemedia%2fabbab6554fa54232bec645b46e6e7bb3f0e4cc5b_size2326_w3000_h2000.JPG&ehk=UzIcp%2fHqCMHntTpDKBDEvAT%2bhhu8xR805ZL0enQCZ%2fY%3d&risl=1&pid=ImgRaw&r=0")
.override(800, 600) // 指定分辨率
.skipMemoryCache(true) // 跳过内存缓存
.diskCacheStrategy(DiskCacheStrategy.ALL) // 全量磁盘缓存
.into(imageView)
核心API设计遵循with().load().into()
三步式结构,隐藏底层复杂实现。
-
with()
:绑定生命周期,初始化并返回RequestManager
。 -
load()
:指定资源(URL、本地路径、资源ID等),返回RequestBuilder
。 -
into()
:触发加载流程,最终显示到Target
(通常是ImageView
)。
Glide执行流程图
java
Glide.with(Activity)
.load(url)
.into(ImageView)
│
├─ with: 创建 RequestManager(绑定生命周期)
│ └─ 注入 SupportRequestManagerFragment 监听生命周期
│
├─ load:构建 RequestBuilder(设置 Model 和 Options)
│
├─ into: 创建 ImageViewTarget(包装 ImageView)
│
├─ into: Engine.load()
│ ├─ 生成 EngineKey(唯一标识请求)
│ ├─ 检查 Active Resources → 命中则直接返回
│ ├─ 检查 Memory Cache → 命中则返回并加入 Active
│ └─ 未命中 → 创建 EngineJob 和 DecodeJob
│ │
│ ├─ DecodeJob.run()
│ │ ├─ 尝试从 RESOURCE_CACHE 加载解码后的资源
│ │ ├─ 尝试从 DATA_CACHE 加载原始数据
│ │ ├─ 从 SOURCE(网络/文件)加载数据
│ │ ├─ 解码数据(使用 BitmapPool 复用)
│ │ └─ 转码为目标类型(Drawable/Gif)
│ │
│ └─ 将结果写入 Active Resources 和 Memory Cache
│
└─ into: 主线程回调 onResourceReady() → 显示图片

Glide 初始化(with)
Kotlin
// 初始化调用链示例
Glide.with(context)
→ Glide.get(context) // 触发GlideBuilder构建实例
→ GlideBuilder.build()
→ 初始化Engine、Registry、MemoryCache等核心组件
→ RequestManagerRetriever.get() // 注入Fragment并绑定生命周期
单例模式
通过双重校验锁(DCL)实现线程安全的单例初始化,首次调用时触发GlideBuilder.build()
。
Kotlin
public static Glide get(Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
//....
GlideBuilder builder = new GlideBuilder(applicationContext);
for (GlideModule module : modules) {
module.applyOptions(applicationContext, builder);
}
glide = builder.createGlide();
for (GlideModule module : modules) {
module.registerComponents(applicationContext, glide);
}
}
}
}
return glide;
}
绑定生命周期
创建透明Fragment以管理Glide生命周期,透明Fragment与外层页面生命周期保持一致。

Glide 通过 Glide.with(context)
中传入的 context 管理生命周期。有以下两种情况:
-
当传入的context是Activity/Fragment上下文时:
- Glide会向当前页面注入透明的Fragment(如
SupportRequestManagerFragment
),该Fragment通过FragmentManager
与页面生命周期同步。在onStart
/onStop
/onDestroy
时(LifecycleListener)触发Glide的请求管理(暂停加载或释放资源)。
- Glide会向当前页面注入透明的Fragment(如
Kotlin
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
RequestManagerFragment current = getRequestManagerFragment(fm);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) {
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
// 在Activity中注入Fragment
current = new RequestManagerFragment();
pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
-
当传入的context为Application上下文或者在非主线程调用
with()
时。- 绑定应用全局生命周期,直接创建RequestManager对象,适用于后台线程或服务等场景。
Kotlin
private RequestManager getApplicationManager(Context context) {
// Either an application context or we're on a background thread.
if (applicationManager == null) {
synchronized (this) {
if (applicationManager == null) {
// Normally pause/resume is taken care of by the fragment we add to the fragment or activity.
// However, in this case since the manager attached to the application will not receive lifecycle
// events, we must force the manager to start resumed using ApplicationLifecycle.
applicationManager = new RequestManager(context.getApplicationContext(),
new ApplicationLifecycle(), new EmptyRequestManagerTreeNode());
}
}
}
return applicationManager;
}
核心组件初始化
负责GlideContext,Engine,Registry 等对象的创建,并向 Registry 中注册各种工具类。

-
RequestManager
:Glide管理中心。-
生命周期管理、请求配置管理、分发调度管理等
-
RequestManager
不直接管理Request
,而是交由RequestTracker
管理Request
的启动,取消,暂停等。
-
-
Engine:任务调度与资源管理核心。负责图片加载执行,协调缓存查找、资源加载、线程调度及生命周期管理:
-
内存缓存管理和磁盘缓存接口(Glide缓存一节阐述)
-
任务调度器和线程池(Glide加载一节阐述)
-
-
Registry:组件注册与数据处理中枢。负责扩展能力,用于注册和管理所有数据处理组件,确保灵活支持多种数据源与处理逻辑。
-
ModelLoader:将复杂数据模型(如 URL、File)转换为可解码的数据流(如
InputStream
)。 -
ResourceDecoder:将原始数据(如
InputStream
)解码为资源(如Bitmap
、GIF
)。 -
Transcoder:转换资源格式(如
Bitmap
转Drawable
),通过BitmapDrawableTranscoder
实现。
-
Glide 加载(load)
负责匹配数据加载器(ModelLoader),并返回DrawableTypeRequest请求对象。
Kotlin
Glide.with(context)
.load(url) // 创建RequestBuilder,匹配ModelLoader
→ loadGeneric(String.class) // 根据数据类型选择ModelLoader
→ 创建DrawableTypeRequest<String>实例
选择数据加载器
ModelLoader<T, Data> :将数据模型(T)转换为可解码的数据流(Data)。我们传入的是String,这块加载的是StreamStringLoader,功能是将URL转为InputStream。我们甚至可以自定义ModelLoader。
Kotlin
// RequestManager.java
public DrawableTypeRequest<String> load(String string) {
return (DrawableTypeRequest<String>) loadGeneric(String.class).load(string);
}
private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) {
// 关键步骤:通过Registry匹配ModelLoader
ModelLoader<T, InputStream> streamLoader =
glide.buildStreamModelLoader(modelClass, context);
ModelLoader<T, ParcelFileDescriptor> fileLoader =
glide.buildFileDescriptorModelLoader(modelClass, context);
return new DrawableTypeRequest<>(modelClass, streamLoader, fileLoader, ...);
}
构造请求构建器
DrawableTypeRequest:针对Drawable资源的请求构建器,继承了DrawableRequestBuilder,管理数据加载、解码、转换流程等;

Glide渲染(into)
Glide 的缓存术语:
Active 内存缓存:正在使用的图片对应的内存缓存
Cache 内存缓存:不在使用的图片对应的内存缓存
Data 磁盘缓存:原始数据对应的磁盘缓存
Resource 磁盘缓存:解码后数据对应的磁盘缓存
流程图

加载流程:
-
请求发起与构建阶段
-
发起图片加载请求:通过
Glide.with(context).load(uri).into(imageView)
等 API 发起加载 -
构建 Request 对象:封装加载参数(URL、宽高、转换规则等);生成唯一的请求标识(Key);确定图片加载优先级。
-
-
多级缓存检查流程
-
活动资源缓存(ActiveResources):存储当前正在使用的图片资源(被 View 引用的图片);使用
WeakReference
+ReferenceQueue
实现,避免内存泄漏;优先检查:若图片正在被使用,直接复用资源。未命中处理:进入内存缓存检查。 -
内存缓存检查(
MemoryCache
):存储近期使用的图片(LruCache 实现);若活动资源缓存未命中,再检查内存缓存;命中后会将图片转移到活动资源缓存中。 -
磁盘缓存检查(
DiskCache
):缓存位置分为SOURCE
(原始资源)和RESULT
(处理后资源)两种类型;命中处理:从磁盘读取缓存文件,解码图片数据并进入后续处理流程;未命中处理:发起网络请求获取图片。
-
-
图片获取与处理阶段
-
网络请求阶段:使用
HttpUrlConnection
或OkHttp
发起请求;支持断点续传和重试机制;下载图片数据到临时文件。 -
图片解码与转换
-
解码流程:使用
BitmapFactory
或ImageDecoder
解码图片''支持自动判断图片格式(JPEG、PNG、WEBP 等)。 -
转换处理:按请求参数进行尺寸缩放(
override(width, height)
);应用图片转换(圆角、高斯模糊、旋转等);支持自定义转换接口(Transformation
)。
-
-
-
缓存与显示阶段
-
缓存处理:内存缓存将处理后的图片存入
LruCache
;活动资源缓存:将正在显示的图片存入ActiveResources
;磁盘缓存:将处理后的图片写入磁盘(RESULT
类型)。 -
图片显示:通过
ImageViewTarget
或自定义 Target 绑定显示组件;支持动画效果(淡入、缩放等);处理图片显示异常(如加载失败、内存不足)。 -
回调与监听:提供了完整的生命周期回调:o
nStart()
:加载开始;onSuccess()
:加载成功;onError()
:加载失败;onResourceReady()
:资源准备完成。
-
关键机制:
-
唯一标识(EngineKey):根据请求参数(URL、尺寸、变换、签名等)生成唯一键,确保缓存匹配和请求合并的准确性。
-
缓存层级与回退:1.查询顺序:
Active缓存
→Memory缓存
→Resource磁盘缓存
→Data磁盘缓存
。2.逐级回退:优先复用活跃资源,逐级下沉查询,最大限度减少耗时操作。 -
请求合并:相同
EngineKey
的请求复用回调,避免重复加载和解码,提升性能。 -
资源释放:1.引用计数:
Active缓存
通过引用计数管理资源生命周期,解绑Target
时计数归零则移入Memory缓存
。2.LRU清理:内存和磁盘缓存按最近最少使用策略淘汰旧资源,防止内存泄漏。
加载阶段:
生成唯一标识(EngineKey)
- 参数收集:根据
load(url)
的输入参数(URL、尺寸override(800,600)
、转换选项centerCrop()
、签名signature()
等)生成唯一标识。 - 哈希计算:将参数组合序列化后,通过
SHA-256
生成哈希值,确保不同参数组合的请求哈希不同。 - 构建 EngineKey:将哈希值与其他上下文参数(如
Target
类型)合并,生成最终EngineKey
。
检查内存缓存
-
ActiveResources 查询:使用
EngineKey
在ActiveResources
(弱引用缓存)中查找正在使用的资源。命中:更新引用计数(acquire()
),直接返回资源。未命中:进入MemoryCache
查询。 -
MemoryCache 查询:使用
EngineKey
在LruResourceCache
(LRU 内存缓存)中查找。命中:资源移至ActiveResources
,引用计数初始化为 1。未命中:进入磁盘缓存查询。

处理重复请求
- 旧请求检测:通过
RequestTracker
检查同一Target
是否已绑定旧请求。 - 取消旧请求:若旧请求未完成,调用
Request#clear()
释放资源并移除任务队列。 - 合并新请求:若新旧请求的
EngineKey
相同,直接复用旧请求的回调,避免重复加载。
查询磁盘缓存
-
Resource 缓存查询:根据
EngineKey
的变体(如尺寸调整后的ResourceCacheKey
)查找已解码资源。命中:解码资源并缓存到ActiveResources
。未命中:进入 Data 缓存查询。 -
Data 缓存查询:根据原始数据标识(
DataCacheKey
)查找未解码的原始数据(如网络响应字节流)。命中:解码数据并应用转换,写入 Resource 缓存(若策略允许)。未命中:触发网络请求。

发起新请求
- 任务创建:
Engine
创建EngineJob
(管理生命周期)和DecodeJob
(执行加载)。 - 线程池分配:
DecodeJob
被提交到GlideExecutor
(磁盘或网络线程池)。 - 数据加载:
- 网络请求:通过
HttpUrlFetcher
下载数据,写入 Data 缓存(若策略为DiskCacheStrategy.DATA
)。 - 本地加载:通过
FileLoader
直接读取文件。
- 网络请求:通过
- 解码与转换:使用
Downsampler
解码数据,应用Transformation
(如CenterCrop
),生成最终资源

缓存更新与资源释放
-
Active缓存写入:新资源通过
Engine#onEngineJobComplete()
加入ActiveResources
。 -
Memory缓存淘汰:当资源引用计数归零时(如
Target
解绑),资源移入MemoryCache
。 -
LRU 清理:当
MemoryCache
或磁盘缓存达到上限时,按 LRU 规则淘汰旧资

图片显示(主线程回调)

-
资源就绪通知:
DecodeJob
完成解码后,通过EngineJob#notifyCallbacksOfResult()
通知主线程。 -
主线程切换:通过
MainThreadExecutor
(内部使用Handler(Looper.getMainLooper())
)切换到主线程。 -
应用资源到 Target:
-
ImageView 显示:调用
ImageViewTarget#onResourceReady()
,将资源(如Bitmap
、Drawable
)设置到ImageView
。 -
动画处理:若配置了过渡动画(如
crossFade()
),通过ViewPropertyTransition.animate()
执行动画。
-
-
错误与占位符处理:
-
加载失败:调用
onLoadFailed()
,显示错误占位符(通过error(Drawable)
配置)。 -
占位符替换:在加载完成前显示
placeholder(Drawable)
,加载成功后替换。
-