Glide 源码浅析
源码参考: glide 4.15.1版本
基本调用流程跟踪
基本调用链 Glide.with(this).load(url).apply(requestOption).into(imageView)
1. Glide.with(this)
创建Glide实例,创建RequestManager实例,关联RequestManager和context生命周期
- Glide提供了多个静态的with重载方法:with方法参数支持
Activity
、Fragment
、FragmentActivity
、View
、Context
- with方法会返回一个
RequestManager
对象, 多个with重载方法源码如下
java
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getContext()).get(fragment);
}
...
接下来通过 getRetriever(context)
获取 RequestManagerRetriever
实例, RequestManagerRetriever
的作用是: 用于创建新的 {@link com.bumptech.glide.RequestManager} 实例,或者从活动(Activity)和片段(Fragment)中获取已存在的实例。 RequestManagerRetriever
是在Glide初始化的时候创建的实例
java
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
// Context could be null for other reasons (ie the user passes in null), but in practice it will
// only occur due to errors with the Fragment lifecycle.
Preconditions.checkNotNull(
context,
"You cannot start a load on a not yet attached View or a Fragment where getActivity() "
+ "returns null (which usually occurs when getActivity() is called before the Fragment "
+ "is attached or after the Fragment is destroyed).");
return Glide.get(context).getRequestManagerRetriever();
}
1.1 Glide
实例 通过Glide.get(context)
获取,Glide是一个单例
GlideBuilder创建Glide实例源码如下:
java
/**
* 构建Glide单例的核心方法
*
* @param context Android上下文(会自动获取ApplicationContext)
* @param manifestModules 从AndroidManifest.xml中解析的GlideModule列表
* @param annotationGeneratedGlideModule 通过@GlideModule注解生成的模块
* @return 完全初始化的Glide实例
*/
public static Glide build(
@NonNull Context context,
List<GlideModule> manifestModules,
AppGlideModule annotationGeneratedGlideModule) {
//===== 线程池配置 =====//
// 源线程池(加载网络/磁盘资源)
if (sourceExecutor == null) {
// 默认配置:
// - 核心线程数 = CPU核心数(至少1,最多4) 内部默认设置最大为4, 如果cpu核心数小于4,则取cpu核心数为核心线程数
// - 最大线程数 = 核心线程数 = CPU核心数(至少1,最多4)
// - 线程空闲保持时间 默认是0 设置为 0 表示立即回收空闲线程 因为最大线程数=核心线程数,所以此处不生效
// - 线程名称前缀 "source-unlimited"
sourceExecutor = GlideExecutor.newSourceExecutor();
}
// 磁盘缓存线程池
if (diskCacheExecutor == null) {
// 专用单线程池:
// - 核心/最大线程数 = 1
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
// 动画资源加载线程池
if (animationExecutor == null) {
// 如果最优线程数>=4, 则最大/核心线程数=2, 否则为1
animationExecutor = GlideExecutor.newAnimationExecutor();
}
//===== 内存计算模块 =====//
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context)
// 默认内存计算规则:
// 总可用内存 = 应用可用内存 * 0.4(默认系数)
// 位图池大小 = 总可用内存 * 0.3(默认系数)
// 内存缓存大小 = 总可用内存 * 0.15(默认系数)
// 数组池大小 = 固定2MB(可通过setArrayPoolSize修改)
.build();
}
//===== 网络监控模块 =====//
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
// 内部使用ConnectivityManager注册广播接收器
// 检测网络状态变化时自动恢复/暂停请求
}
//===== 缓存池初始化 =====//
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
if (size > 0) {
// LRU位图池,缓存大小由MemorySizeCalculator计算
// 默认策略:最近最少使用算法
bitmapPool = new LruBitmapPool(size);
} else {
// 空实现,用于禁用位图池的场景
bitmapPool = new BitmapPoolAdapter();
}
}
if (arrayPool == null) {
// 数组缓存池,默认大小4MB(由MemorySizeCalculator计算)
// 用于复用byte[]、int[]等临时数组,减少GC
arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
}
if (memoryCache == null) {
// 内存缓存,默认使用应用可用内存的15%
// 缓存条目为Resource对象,包含Bitmap和其他资源
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
}
//===== 磁盘缓存 =====//
if (diskCacheFactory == null) {
// 默认使用内部私有目录缓存:
// 缓存路径:/data/data/<package_name>/image_manager_disk_cache
// 默认大小250MB(当剩余空间足够时)
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
//===== 核心引擎初始化 =====//
if (engine == null) {
engine = new Engine(
memoryCache, // 内存缓存
diskCacheFactory, // 磁盘缓存工厂
diskCacheExecutor, // 磁盘缓存线程池
sourceExecutor, // 源线程池
GlideExecutor.newUnlimitedSourceExecutor(), // 无限制线程池(用于预加载)
animationExecutor, // 动画线程池
isActiveResourceRetentionAllowed // 是否保留活动资源标志
);
// Engine是Glide的核心调度器,负责:
// 1. 管理活动资源(正在使用的资源)
// 2. 协调内存/磁盘缓存
// 3. 处理线程调度
}
//===== 默认请求监听器 =====//
if (defaultRequestListeners == null) {
defaultRequestListeners = Collections.emptyList();
} else {
// 防止外部修改
defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
}
//===== 实验性功能配置 =====//
GlideExperiments experiments = glideExperimentsBuilder.build();
// 包含通过@ExperimentalFeature注解启用的功能
//===== 请求管理器检索器 =====//
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory, experiments);
// 负责将RequestManager绑定到生命周期:
// - Activity/Fragment生命周期感知
// - 使用无视图Fragment监听生命周期
//===== 最终构建Glide实例 =====//
return new Glide(
context.getApplicationContext(), // 使用应用级上下文防止内存泄漏
engine, // 核心引擎
memoryCache, // 内存缓存
bitmapPool, // 位图池
arrayPool, // 数组池
requestManagerRetriever, // 生命周期管理器
connectivityMonitorFactory, // 网络状态监控
logLevel, // 日志级别(默认Log.ERROR)
defaultRequestOptionsFactory, // 默认请求配置工厂
defaultTransitionOptions, // 默认过渡动画配置
defaultRequestListeners, // 全局请求监听器
manifestModules, // 清单文件模块(兼容旧版)
annotationGeneratedGlideModule, // 注解生成的配置模块
experiments // 实验性功能
);
}
1.1.1 线程池配置
- 源线程池(加载网络/磁盘资源)最大线程数 = 核心线程数 = CPU核心数(至少1,最多4;
- 磁盘缓存线程池,核心/最大线程数 = 1;
- 动画线程池,如果glide源线程池>=4, 则最大/核心线程数=2, 否则为1.
- Engine中的GlideExecutor.newUnlimitedSourceExecutor(), // 无限制线程池(用于预加载)
1.1.2 缓存池初始化:
bitmapPool
: 位图池, 默认使用LruBitmapPool(存储在内存中GroupedLinkedMap),缓存大小由MemorySizeCalculator计算memoryCache
: 内存缓存, 默认使用LruResourceCache,缓存条目为Resource对象,包含Bitmap和其他资源diskCacheFactory
: 磁盘缓存工厂,默认使用InternalCacheDiskCacheFactory,缓存路径:/data/data/<package_name>/image_manager_disk_cache, 默认大小250MB(当剩余空间足够时)arrayPool
: 默认使用LruArrayPool,缓存大小为4MB(由MemorySizeCalculator计算) 用于复用byte[]、int[]等临时数组,减少GC
在 Glide 中,当 bitmapPool
,memoryCache
和 diskCacheFactory
三者都存在时,它们的优先级顺序如下:
-
bitmapPool(Bitmap 池):
- 优先级:最高
- 原因 :bitmapPool用于复用
Bitmap
对象,避免频繁创建和销毁Bitmap
,从而减少内存分配和垃圾回收的开销。Glide 在加载图片时,会首先尝试从 bitmapPool中获取可复用的Bitmap
对象。如果找到合适的Bitmap
,则直接复用,否则会创建一个新的Bitmap
。
-
memoryCache(内存缓存):
- 优先级:次高
- 原因 :memoryCache 用于缓存已经解码的图片资源(Resource),以便在后续请求中快速获取,而不需要重新解码。当bitmapPool中没有可复用的
Bitmap
时,Glide 会检查 memoryCache中是否已经缓存了该图片。如果缓存命中,则直接使用缓存中的资源;否则,会继续从磁盘缓存或网络加载。
-
diskCacheFactory(磁盘缓存工厂):
- 优先级:最低
- 原因:diskCacheFactory 用于创建磁盘缓存,将图片资源持久化存储在设备的磁盘上,以便在应用重启后仍然可以快速加载。当 bitmapPool 和 memoryCache中都没有找到所需的资源时,Glide 会检查磁盘缓存。如果磁盘缓存中存在该资源,则从磁盘加载;否则,会从网络下载并缓存到磁盘。
总结
- bitmapPool :优先复用
Bitmap
对象,减少内存分配和垃圾回收。 - memoryCache:次优先使用内存缓存,加速后续加载。
- diskCacheFactory:最后使用磁盘缓存,持久化存储图片资源。
这种优先级顺序确保了 Glide 在加载图片时能够最大限度地复用资源,减少网络请求和资源解码的开销,从而优化性能。
疑问点: bitmapPool是缓存位图的, memoryCache缓存的是Resource对象, Resource对象包含了bitmap了,为啥还单独存储了一个bitmappool呢?
-
BitmapPool 专注于 Bitmap 内存复用,避免因频繁创建/销毁 Bitmap 导致以下问题:
- 内存抖动:频繁触发 GC,导致界面卡顿
- 分配延迟:Bitmap.createBitmap() 的 CPU 开销
- 存储未加工的 Bitmap 内存块,可被任何请求复用(只要尺寸匹配)
java// 不同URL但相同尺寸的图片,可能复用同一Bitmap内存 Bitmap bitmap1 = bitmapPool.get(100, 100, ARGB_8888); // URL1 Bitmap bitmap2 = bitmapPool.get(100, 100, ARGB_8888); // URL2
-
MemoryCache
- 提供 完整资源的快速访问,避免重复解码、转码、变换等计算:
java// MemoryCache 缓存的是"成品"资源 Resource<Drawable> resource = memoryCache.get(key); if (resource != null) { target.onResourceReady(resource); // 直接使用缓存 }
- 存储特定请求的最终结果(如圆形裁剪后的图片)
java// 同一URL但不同变换的图片,需要不同缓存条目 memoryCache.get(key1); // 原图 memoryCache.get(key2); // 圆形裁剪后的图
1.1.3 Engine创建
glideEngine创建
java
if (engine == null) {
engine =
new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
animationExecutor,
isActiveResourceRetentionAllowed);
}
Engine
是 Glide 的核心组件之一,负责管理图片加载的生命周期、资源缓存、线程池调度等。它的主要职责包括:
- 资源加载:
- 负责从内存缓存、磁盘缓存或网络加载图片资源。 协调
BitmapPool
、MemoryCache
和DiskCache
的使用,确保资源的高效复用。
- 缓存管理:
- 管理内存缓存(
MemoryCache
)和磁盘缓存(DiskCache
),确保资源在合适的时间被缓存和释放。 通过BitmapPool
复用 Bitmap 对象,减少内存分配和垃圾回收的开销。
- 线程池调度:
- 使用多个线程池(如
sourceExecutor
、diskCacheExecutor
、animationExecutor
)来执行不同的任务,确保图片加载的高效性和流畅性。
- 资源回收:
- 根据
isActiveResourceRetentionAllowed
参数决定是否允许保留活跃资源,避免资源被过早回收。
第五个参数详解 GlideExecutor.newUnlimitedSourceExecutor()
java
public static GlideExecutor newUnlimitedSourceExecutor() {
return new GlideExecutor(
new ThreadPoolExecutor(
0, // 核心线程数(没有常驻线程)
Integer.MAX_VALUE, // 最大线程数(理论无上限)
KEEP_ALIVE_TIME_MS,// 线程空闲存活时间(10毫秒)
TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>(), // 同步移交队列
new DefaultThreadFactory(
new DefaultPriorityThreadFactory(),
DEFAULT_SOURCE_UNLIMITED_EXECUTOR_NAME,
UncaughtThrowableStrategy.DEFAULT,
false)));
}
-
关键设计:SynchronousQueue + 极短存活时间 队列特性与常规队列对比:
队列类型 存储能力 任务传递方式 适用场景 SynchronousQueue 零容量 直接移交(生产者-消费者配对) 需要瞬时创建线程的高吞吐场景 LinkedBlockingQueue 无界/有界 缓冲任务,先进先出 常规任务队列(需控制并发数) PriorityBlockingQueue 无界 按优先级排序 需要任务优先级的场景(如主线程) -
行为模式:
- 没有核心线程,所有任务立即创建新线程执行
- 线程空闲 10ms 后立即销毁
- 队列无法存储任务,必须立即移交线程处理
为什么要这样设计?
- 专属场景:预加载(Preload)
java
// 使用示例:
Glide.with(context)
.load(url)
.preload(); // 预加载到缓存但不显示
- 预加载特性:
- 低优先级:不影响当前可见图片的加载
- 可丢弃性:即使未完成也不会影响用户体验
- 数量可控:通常由开发者主动触发,总量有限
- 与常规加载的隔离
- 常规线程池(sourceExecutor):
- 用于可见图片的即时加载
- 有严格的核心线程限制(最大为4)
- 优先级队列保证可见图片优先执行
- 无限制线程池:
- 单独处理预加载任务
- 避免抢占常规线程池资源
这种设计体现了 空间换时间 的优化思想:
- 瞬时资源抢占:通过爆发性创建线程快速完成任务
- 快速资源释放:利用极短的 KeepAlive 时间及时回收
- 场景隔离:与常规加载线程池(SourceExecutor)分离,避免相互影响
1.1.4 Glide实例对象 ,RequestManagerRetriever创建
创建RequestManagerRetriever实例,用于获取RequestManager 创建Glide实例对象
java
return new Glide(
context, // 上下文对象,用于访问应用资源和配置
engine, // Glide 的核心引擎,负责管理资源加载、缓存和线程池调度
memoryCache, // 内存缓存,用于缓存已解码的图片资源,加速后续加载
bitmapPool, // Bitmap 池,用于复用 Bitmap 对象,减少内存分配和垃圾回收
arrayPool, // 数组池,用于复用临时数组,减少内存分配
requestManagerRetriever, // 请求管理器检索器,用于获取和管理 RequestManager 实例
connectivityMonitorFactory, // 网络连接监控工厂,用于监听网络状态变化
logLevel, // 日志级别,控制 Glide 的日志输出详细程度
defaultRequestOptionsFactory, // 默认请求选项工厂,用于生成默认的 RequestOptions
defaultTransitionOptions, // 默认过渡选项,用于定义资源加载完成后的过渡动画
defaultRequestListeners, // 默认请求监听器列表,用于监听所有请求的生命周期事件
manifestModules, // 清单模块列表,用于加载 GlideModule 配置
annotationGeneratedGlideModule, // 注解生成的 GlideModule,用于自定义 Glide 配置
experiments // 实验性功能配置,用于启用或禁用 Glide 的实验性功能
);
1.2 RequestManager通过getRetriever(fragment.getContext()).get(fragment/activity/FragmentActivity/context/view)
获取
在 Glide 中,getRetriever(fragment.getContext()).get(...) 是一个常见的调用方式,用于获取 RequestManager 实例。根据传入的参数类型不同,Glide 会采取不同的策略来管理请求的生命周期。以下是五种情况的详细解释:
1.2.1 get(fragment)
包含两种情况:
- fragment是Androidx.fragment
java
// 1. RequestManagerRetriever.java
@NonNull
public RequestManager get(@NonNull Fragment fragment) {
Preconditions.checkNotNull(
fragment.getContext(),
"You cannot start a load on a fragment before it is attached or after it is destroyed");
if (Util.isOnBackgroundThread()) {
return get(fragment.getContext().getApplicationContext());
}
// frameWaiter 的作用是确保 Glide 在合适的时机执行操作,避免在 Activity 或 Fragment 尚未完全初始化时加载图片,从而提升应用的性能和稳定性
// 此处代码作用是将 Fragment 所属的 Activity 注册到 frameWaiter 中,以便 frameWaiter 可以监听 Activity 的生命周期事件并等待合适的时机执行操作。
if (fragment.getActivity() != null) {
frameWaiter.registerSelf(fragment.getActivity());
}
FragmentManager fm = fragment.getChildFragmentManager();
Context context = fragment.getContext();
Glide glide = Glide.get(context.getApplicationContext());
return lifecycleRequestManagerRetriever.getOrCreate(
context, glide, fragment.getLifecycle(), fm, fragment.isVisible());
}
// 2. LifecycleRequestManagerRetriever.getOrCreate(...)
RequestManager getOrCreate(
Context context,
Glide glide,
final Lifecycle lifecycle,
FragmentManager childFragmentManager,
boolean isParentVisible) {
Util.assertMainThread();
RequestManager result = getOnly(lifecycle);
if (result == null) {
LifecycleLifecycle glideLifecycle = new LifecycleLifecycle(lifecycle);
result =
factory.build(
glide,
glideLifecycle,
new SupportRequestManagerTreeNode(childFragmentManager),
context);
lifecycleToRequestManager.put(lifecycle, result);
glideLifecycle.addListener(
new LifecycleListener() {
@Override
public void onStart() {}
@Override
public void onStop() {}
@Override
public void onDestroy() {
lifecycleToRequestManager.remove(lifecycle);
}
});
// This is a bit of hack, we're going to start the RequestManager, but not the
// corresponding Lifecycle. It's safe to start the RequestManager, but starting the
// Lifecycle might trigger memory leaks. See b/154405040
if (isParentVisible) {
result.onStart();
}
}
return result;
}
- 将当前fragment所属的lifecycle和RequestManager进行绑定,通过getOnly(lifecycle),获取指定的Requestmanager, 如果不存在就通过RequestManagerFactory创建RequestManager, 并以fragment的lifecycle为key, RequestManager为value保存到对应的HashMap集合中
- RequestManagerFactory.build(...)方法中,传入了SupportRequestManagerTreeNode, 此对象用于管理RequestManager树节点, 可以管理所有fragment节点下的RequestManager
- fragment是android.app.Fragment
java
/**
* @deprecated Use androidx fragments instead: {@link Fragment}.
*/
@SuppressWarnings("deprecation")
@Deprecated
@NonNull
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public RequestManager get(@NonNull android.app.Fragment fragment) {
if (fragment.getActivity() == null) {
throw new IllegalArgumentException(
"You cannot start a load on a fragment before it is attached");
}
if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
return get(fragment.getActivity().getApplicationContext());
} else {
if (fragment.getActivity() != null) {
// frameWaiter 的作用是确保 Glide 在合适的时机执行操作,避免在 Activity 或 Fragment 尚未完全初始化时加载图片,从而提升应用的性能和稳定性
frameWaiter.registerSelf(fragment.getActivity());
}
android.app.FragmentManager fm = fragment.getChildFragmentManager();
return fragmentGet(fragment.getActivity(), fm, fragment, fragment.isVisible());
}
}
//---- fragmentGet(...)
@Deprecated
@NonNull
private RequestManager fragmentGet(
@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context);
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
// This is a bit of hack, we're going to start the RequestManager, but not the
// corresponding Lifecycle. It's safe to start the RequestManager, but starting the
// Lifecycle might trigger memory leaks. See b/154405040
if (isParentVisible) {
requestManager.onStart();
}
current.setRequestManager(requestManager);
}
return requestManager;
}
//---获取一个无界面的RequestManagerFragment
@SuppressWarnings("deprecation")
@NonNull
private RequestManagerFragment getRequestManagerFragment(
@NonNull final android.app.FragmentManager fm, @Nullable android.app.Fragment parentHint) {
// If we have a pending Fragment, we need to continue to use the pending Fragment. Otherwise
// there's a race where an old Fragment could be added and retrieved here before our logic to
// add our pending Fragment notices. That can then result in both the pending Fragmeng and the
// old Fragment having requests running for them, which is impossible to safely unwind.
RequestManagerFragment current = pendingRequestManagerFragments.get(fm);
if (current == null) {
current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
- 如果在后台或者sdkInt<17 使用全局AplicationContext的RequestManager
- sdkInt>=17, 会创建一个无界面的RequestManagerFragment, 获取当前fragment的Requestmanager对象,并和Requestmanager绑定其生命周期
1.2.2 get(activity)
java
@Deprecated
@SuppressWarnings("deprecation")
@NonNull
public RequestManager get(@NonNull Activity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else if (activity instanceof FragmentActivity) {
return get((FragmentActivity) activity);
} else {
assertNotDestroyed(activity);
frameWaiter.registerSelf(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(activity, fm, /* parentHint= */ null, isActivityVisible(activity));
}
}
- 是否在后台, 如果是 则使用全局AplicationContext的RequestManager
- 是否是FragmentActivity, 如果是则使用FragmentActivity的RequestManager
- 否则, 创建一个无界面的RequestManagerFragment, 获取当前activity的Requestmanager对象,并和Requestmanager绑定其生命周期
1.2.3 get(FragmentActivity)
java
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
}
assertNotDestroyed(activity);
frameWaiter.registerSelf(activity);
boolean isActivityVisible = isActivityVisible(activity);
Glide glide = Glide.get(activity.getApplicationContext());
return lifecycleRequestManagerRetriever.getOrCreate(
activity,
glide,
activity.getLifecycle(),
activity.getSupportFragmentManager(),
isActivityVisible);
}
- 获取/创建当前FragmentActivity的Requestmanager对象,并和Lifecycle绑定生命周期
1.2.4 get(view)
java
@SuppressWarnings("deprecation")
@NonNull
public RequestManager get(@NonNull View view) {
if (Util.isOnBackgroundThread()) {
return get(view.getContext().getApplicationContext());
}
Preconditions.checkNotNull(view);
Preconditions.checkNotNull(
view.getContext(), "Unable to obtain a request manager for a view without a Context");
Activity activity = findActivity(view.getContext());
// The view might be somewhere else, like a service.
if (activity == null) {
return get(view.getContext().getApplicationContext());
}
//
if (activity instanceof FragmentActivity) {
Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
return fragment != null ? get(fragment) : get((FragmentActivity) activity);
}
// Standard Fragments.
android.app.Fragment fragment = findFragment(view, activity);
if (fragment == null) {
return get(activity);
}
return get(fragment);
}
- 获取view挂载的activity, 如果是FragmentActivity, 则使用FragmentActivity的RequestManager
- 否则, 获取view对应的fragment, 如果有则使用fragment的RequestManager, 否则使用activity的RequestManager
1.2.5 get(context)
- 获取全局AplicationContext的RequestManager
1.3 总结
Glide.with()方法的作用是:
- 创建单例的Glide对象, 并且配置了线程池,缓存池, Engine, RequestManager追踪器RequestManagerRetriever
- 绑定RequestManager和 1.AndroidX版本是当前activity/fragment的生命周期 2.非AndroidX版本是创建了一个不可视的RequestManagerFragment的生命周期
2. load()方法
load方法同样的也是有多个重载方法
java
public GlideRequest<Drawable> load(@Nullable Bitmap bitmap) {
return (GlideRequest<Drawable>) super.load(bitmap);
}
public GlideRequest<Drawable> load(@Nullable Drawable drawable) {
return (GlideRequest<Drawable>) super.load(drawable);
}
public GlideRequest<Drawable> load(@Nullable String string) {
return (GlideRequest<Drawable>) super.load(string);
}
public GlideRequest<Drawable> load(@Nullable Uri uri) {
return (GlideRequest<Drawable>) super.load(uri);
}
public GlideRequest<Drawable> load(@Nullable File file) {
return (GlideRequest<Drawable>) super.load(file);
}
public GlideRequest<Drawable> load(@RawRes @DrawableRes @Nullable Integer id) {
return (GlideRequest<Drawable>) super.load(id);
}
public GlideRequest<Drawable> load(@Nullable URL url) {
return (GlideRequest<Drawable>) super.load(url);
}
public GlideRequest<Drawable> load(@Nullable byte[] bytes) {
return (GlideRequest<Drawable>) super.load(bytes);
}
public GlideRequest<Drawable> load(@Nullable Object o) {
return (GlideRequest<Drawable>) super.load(o);
}
返回对象均为 RequestBuilder的子类,并且全部转为了GlideRequest <Drawable>
, 以上目的是将加载参数放入requestBuilder中, 后续into会调用RequestBuilder的buildRequest方法将load的参数用于创建Request对象
3. into()方法
3.1 into(imageView)方法
java
@NonNull
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
BaseRequestOptions<?> requestOptions = this;
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
switch (view.getScaleType()) {
case CENTER_CROP:
requestOptions = requestOptions.clone().optionalCenterCrop();
break;
case CENTER_INSIDE:
requestOptions = requestOptions.clone().optionalCenterInside();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
requestOptions = requestOptions.clone().optionalFitCenter();
break;
case FIT_XY:
requestOptions = requestOptions.clone().optionalCenterInside();
break;
case CENTER:
case MATRIX:
default:
// Do nothing.
}
}
return into(
glideContext.buildImageViewTarget(view, transcodeClass),
/* targetListener= */ null,
requestOptions,
Executors.mainThreadExecutor());
}
-
- 获取图片展示配置赋值给 requestOptions
-
- 调用into(tartget, targetListener, requestOptions, callbackExecutor) 方法
3.1.1 四个参数解析
glideContext.buildImageViewTarget(view, transcodeClass)
java
// GlideContext.java
public <X> ViewTarget<ImageView, X> buildImageViewTarget(
@NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
}
// ImageViewTargetFactory
public <Z> ViewTarget<ImageView, Z> buildTarget(
@NonNull ImageView view, @NonNull Class<Z> clazz) {
if (Bitmap.class.equals(clazz)) {
return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException(
"Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
- 第一个参数. 从load方法中最终全部转为了GlideRequest
<Drawable>
,也就是默认情况下 transcodeClass = Drawable; 所以默认会得到DrawableImageViewTarget, 调用了asBitmap()方法后会得到transcodeClass = BitmapImageViewTarget - 第二个参数: 默认为null
- 第三个参数: imageView配置
- 第四个参数: 回调线程设置会主线程
3.2 into(tartget, targetListener, requestOptions, callbackExecutor)方法
RequstBuilder类内部into方法内通过buildRequest创建Request对象, 通过Engine管理请求/线程池/缓存池的调度, 如果未命中缓存,最终再发起请求
java
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
// 创建request
Request request = buildRequest(target, targetListener, options, callbackExecutor);
// 请求复用检查,获取目标上已有的请求(可能正在进行或已完成)
Request previous = target.getRequest();
// 判断新旧请求是否等效(相同URL、相同配置等)
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
// 若旧请求未在运行中,则重新开始(触发回调)
if (!Preconditions.checkNotNull(previous).isRunning()) {
// (1) 重新启动请求但复用已有资源
previous.begin();
}
// 请求正在执行,直接返回避免重复请求
return target;
}
//===== 新请求处理流程 =====//
// 清理目标上关联的旧请求
requestManager.clear(target);
// 将新请求绑定到目标
target.setRequest(request);
// (2) 跟踪并启动新请求
requestManager.track(target, request);
return target;
}
- 创建request
- 复用检查,获取目标上已有请求 如果新旧请求等效,判断请求是否在执行中, 如果正在执行,直接返回避免重复请求; 否则重启请求,复用已有资源
- 新请求开始,请求target绑定, 关联新的Request, 跟踪并启动新请求
3.2.1 (1)处: previous.begin()
java
// SingleRequest.java
@Override
public void begin() {
synchronized (requestLock) {
assertNotCallingCallbacks();
stateVerifier.throwIfRecycled();
startTime = LogTime.getLogTime();
// model 是load(model)进来的对象, 不能为null
if (model == null) {
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
width = overrideWidth;
height = overrideHeight;
}
int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
onLoadFailed(new GlideException("Received null model"), logLevel);
return;
}
// 状态进行中 说明前面拦截失败 直接报错
if (status == Status.RUNNING) {
throw new IllegalArgumentException("Cannot restart a running request");
}
// 状态已完成回调
if (status == Status.COMPLETE) {
onResourceReady(
resource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);
return;
}
// 通知请求开始的事件给监听器
experimentalNotifyRequestStarted(model);
cookie = GlideTrace.beginSectionAsync(TAG);
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
// 资源准备就绪 执行复用/请求 逻辑
onSizeReady(overrideWidth, overrideHeight);
} else {
// 异步获取size
target.getSize(this);
}
if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
&& canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable());
}
if (IS_VERBOSE_LOGGABLE) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}
}
/** A callback method that should never be invoked directly. */
// 应为是begin是资源复用阶段, 如果已存在则无需再等待size准备阶段,可以直接调用
@Override
public void onSizeReady(int width, int height) {
stateVerifier.throwIfRecycled();
synchronized (requestLock) {
if (IS_VERBOSE_LOGGABLE) {
logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
if (status != Status.WAITING_FOR_SIZE) {
return;
}
status = Status.RUNNING;
float sizeMultiplier = requestOptions.getSizeMultiplier();
this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
if (IS_VERBOSE_LOGGABLE) {
logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
}
loadStatus =
engine.load(
glideContext,
model,
requestOptions.getSignature(),
this.width,
this.height,
requestOptions.getResourceClass(),
transcodeClass,
priority,
requestOptions.getDiskCacheStrategy(),
requestOptions.getTransformations(),
requestOptions.isTransformationRequired(),
requestOptions.isScaleOnlyOrNoTransform(),
requestOptions.getOptions(),
requestOptions.isMemoryCacheable(),
requestOptions.getUseUnlimitedSourceGeneratorsPool(),
requestOptions.getUseAnimationPool(),
requestOptions.getOnlyRetrieveFromCache(),
this,
callbackExecutor);
if (status != Status.RUNNING) {
loadStatus = null;
}
if (IS_VERBOSE_LOGGABLE) {
logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
}
}
begin
判断资源是否准备完成, 如果已准备完成进入onSizeReady
阶段,否则getSize异步获取尺寸 → 触发 onSizeReady()- 在
onSizeReady
中 设置状态为Status.RUNNING, 执行engine.load()
java
begin()
├─ onSizeReady() // 尺寸就绪
│ └─ engine.load() // 进入引擎加载
│ ├─ 检查活动资源
│ ├─ 检查内存缓存
│ ├─ 检查磁盘缓存
│ └─ 发起网络请求(如需要)
└─ target.getSize() → 异步获取尺寸 → 触发 onSizeReady()
engine.load()详解
java
/**
* Glide引擎加载资源的核心方法,负责协调内存缓存、磁盘缓存和资源生成
*
* @param <R> 转码后的资源类型(如Drawable)
* @param glideContext Glide上下文,包含注册组件
* @param model 数据源标识(如URL/File/Uri)
* @param signature 唯一签名(用于缓存版本控制)
* @param width 目标宽度
* @param height 目标高度
* @param resourceClass 原始资源类型(如Bitmap)
* @param transcodeClass 目标转码类型(如Drawable)
* @param priority 请求优先级
* @param diskCacheStrategy 磁盘缓存策略
* @param transformations 变换操作集合
* @param isTransformationRequired 是否必须应用变换
* @param options 解码选项
* @param isMemoryCacheable 是否启用内存缓存
* @param cb 资源回调接口
* @param callbackExecutor 回调执行器(主线程)
* @return LoadStatus 用于跟踪或取消加载
*/
public <R> LoadStatus load(...) {
long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
// 生成唯一缓存键(包含所有影响资源生成的参数)
EngineKey key =
keyFactory.buildKey(
model,
signature,
width,
height,
transformations,
resourceClass,
transcodeClass,
options);
// 同步块保证内存缓存操作的原子性
EngineResource<?> memoryResource;
synchronized (this) {
// 1. 检查内存缓存(活动资源+LRU缓存)
memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
if (memoryResource == null) {
// 2. 缓存未命中,进入异步加载流程
return waitForExistingOrStartNewJob(...);
}
}
// 3. 命中缓存 回调缓存资源
cb.onResourceReady(
memoryResource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);
return null;
}
// 缓存检查代码
EngineResource<?> loadFromMemory(EngineKey key, boolean isMemoryCacheable, long startTime) {
// 检查活动资源(正在使用的资源)
EngineResource<?> active = loadActiveResources(key);
if (active != null) return active;
// 检查LRU内存缓存(需isMemoryCacheable=true)
EngineResource<?> cached = loadFromCache(key);
if (cached != null) {
// 移入活动资源
activeResources.activate(key, cached);
return cached;
}
return null;
}
- 获取缓存资源, 如果命中了 则直接进入(3) 回调资源
- 如果缓存未命中 执行异步加载流程(2)waitForExistingOrStartNewJob, 源码分析如下
java
//主要参数说明
/*
* @param key 唯一标识请求的复合键(包含尺寸、变换、数据源等参数)
* @param onlyRetrieveFromCache 是否仅从缓存加载(不发起网络请求)
* @param cb 资源回调接口,用于接收加载结果
* @param callbackExecutor 回调执行器(通常是主线程的 MainThreadExecutor)
*/
private <R> LoadStatus waitForExistingOrStartNewJob(...) {
// 检查任务
EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
// 复用现有任务
current.addCallback(cb, callbackExecutor);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
// 创建新任务 管理任务状态、处理线程调度、协调多个回调。
EngineJob<R> engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
// 执行实际的资源加载、解码、转码流程
DecodeJob<R> decodeJob =
decodeJobFactory.build(...);
// 加入全局任务表, 供后续请求复用
jobs.put(key, engineJob);
// (1) 添加资源结果回调,并将每个回调添加到cbs(全局列表中),以便于decodeJob资源完成之后,遍历cbs再次执行回调
engineJob.addCallback(cb, callbackExecutor);
// (2) 内部将 DecodeJob 提交到适当线程池:
// - 磁盘缓存:GlideExecutor (diskCacheExecutor)
// - 网络请求:GlideExecutor (sourceExecutor)
// - 动画: GlideExecutor(animationExecutor)
engineJob.start(decodeJob);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new LoadStatus(cb, engineJob);
}
- (1)处 将cb(ResourceCallback) 存储到全局的cbs内, 编于decode完成后 遍历所有cbs并回调
- 回调添加时资源已就绪 → 立即提交到主线程队列(但非立即执行)
- 回调添加时资源未就绪 → 暂存回调,待后续解码完成后再触发
java
synchronized void addCallback(final ResourceCallback cb, Executor callbackExecutor) {
stateVerifier.throwIfRecycled();
// 存储到EngineJob的cbs中, EngineJob在初始化Engin时创建,所以是全局的
cbs.add(cb, callbackExecutor);
// 如果已有资源,则将任务加入到主线程的MessageQueue,待Looper处理到时执行run方法, decode成功后会执行到EngineJob的onResourceReady方法内,hasResource在这里设置为true,
if (hasResource) {
incrementPendingCallbacks(1);
callbackExecutor.execute(new CallResourceReady(cb));
} else if (hasLoadFailed) {
incrementPendingCallbacks(1);
callbackExecutor.execute(new CallLoadFailed(cb));
} else {
Preconditions.checkArgument(!isCancelled, "Cannot add callbacks to a cancelled EngineJob");
}
}
- (2)处 将DecodeJob放到对应的线程池中执行,下面是对应的判断使用对应线程池的具体代码 DecodeJob 是 Glide 图片加载框架中的核心工作单元,负责协调 数据获取、解码、转码、缓存 等关键流程。它的作用可以概括为:将原始数据源(如 URL、File 等)转换为目标可用的资源(如 Bitmap、Drawable),同时遵循 Glide 的缓存策略和线程模型。
java
// EngineJob.java
public synchronized void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor =
decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
executor.execute(decodeJob);
}
private GlideExecutor getActiveSourceExecutor() {
return useUnlimitedSourceGeneratorPool
? sourceUnlimitedExecutor
: (useAnimationPool ? animationExecutor : sourceExecutor);
}
DecodeJob.java 的核心代码注释如下: 该实现通过状态机和责任链模式,将复杂的解码流程分解为可管理的阶段,既保证了各环节的独立性,又通过统一的异常处理机制确保了系统稳定性。
java
/**
* DecodeJob的核心执行方法,运行在指定的线程池中(如磁盘缓存线程或源线程)
* 职责:协调整个解码流程,处理异常,确保资源清理
*/
@Override
public void run() {
// 开始性能跟踪区块(用于Debug时查看方法耗时)
GlideTrace.beginSectionFormat("DecodeJob#run(reason=%s, model=%s)", runReason, model);
// 使用局部变量持有当前数据抓取器,确保finally块中能正确清理
DataFetcher<?> localFetcher = currentFetcher;
try {
// 检查任务是否已被取消
if (isCancelled) {
notifyFailed(); // 通知失败回调
return;
}
runWrapped(); // 进入核心处理流程
} catch (CallbackException e) {
// 透传非Glide控制的回调异常(通常由用户代码引起)
throw e;
} catch (Throwable t) { // 捕获所有异常包括Error(如OOM)
// 调试日志记录
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG,"DecodeJob threw unexpectedly, isCancelled: "+isCancelled+", stage: "+stage, t);
}
// 非编码阶段收集异常并通知失败
if (stage != Stage.ENCODE) {
throwables.add(t);
notifyFailed();
}
// 如果未被显式取消,重新抛出异常
if (!isCancelled) throw t;
throw t; // 已取消的请求仍抛出但会被EngineJob忽略
} finally {
// 清理数据抓取器资源(如关闭网络连接)
if (localFetcher != null) {
localFetcher.cleanup();
}
GlideTrace.endSection(); // 结束性能跟踪
}
}
/**
* 根据当前运行原因(RunReason)执行对应的处理阶段
*/
private void runWrapped() {
switch (runReason) {
case INITIALIZE: // 初始运行(首次进入或重试)
// 确定下一个处理阶段(资源缓存->数据缓存->源数据)
stage = getNextStage(Stage.INITIALIZE);
// 获取对应阶段的生成器(如ResourceCacheGenerator)
currentGenerator = getNextGenerator();
runGenerators(); // 启动生成器执行
break;
case SWITCH_TO_SOURCE_SERVICE: // 切换到源数据服务
runGenerators(); // 继续执行生成器(通常已切换至SourceGenerator)
break;
case DECODE_DATA: // 数据就绪,进行解码
decodeFromRetrievedData(); // 执行解码流程
break;
default:
throw new IllegalStateException("Unrecognized run reason: " + runReason);
}
}
3.2.2 (2)处: requestManager.track(target, request)
java
// RequestManager.java
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
// 跟踪目标对象
targetTracker.track(target);
// 管理加载请求
requestTracker.runRequest(request);
}
// RequestTracker.java
public void runRequest(@NonNull Request request) {
requests.add(request); // 步骤1:记录所有请求
if (!isPaused) { // 步骤2:检查暂停状态
request.begin(); // 步骤2a:未暂停,立即启动
} else {
request.clear(); // 步骤2b:已暂停,取消请求
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Paused, delaying request");
}
pendingRequests.add(request); // 步骤3:加入待定队列
}
}
// TargetTracker类(简略)
public class TargetTracker {
private final Set<Target<?>> targets = Collections.newSetFromMap(new WeakHashMap<>());
public void track(@NonNull Target<?> target) {
targets.add(target); // 使用WeakHashMap防止内存泄漏
}
}
track的作用
- 使用弱引用集合存储 Target,当外部(如 Activity)销毁时,Target 可被自动回收。
- 页面销毁时,TargetTracker 可自动清除所有跟踪的 Target,终止关联的请求。
requests集合的作用
- 全局管理所有活跃请求(无论是否暂停),用于批量操作(如暂停时取消所有请求)。
- isPaused 字段来源: 通过 RequestTracker 的 pauseRequests()/resumeRequests() 方法设置。常见触发场景:
设计原理总结
- 生命周期整合 场景:当应用进入后台 (onStop),暂停所有请求以避免不必要的 CPU/网络消耗。 恢复机制:返回前台时 (onStart),从 pendingRequests 重启请求,确保界面自动刷新。
- 内存安全 弱引用追踪:TargetTracker 使用弱引用集合,避免因 Target 未释放导致的内存泄漏。 资源回收:请求暂停时,request.clear() 及时释放资源(如 Bitmap 的引用)。
- 线程安全 同步控制:synchronized 块确保并发环境下,请求的添加和状态判断是原子的。 数据结构选择:requests 和 pendingRequests 通常使用线程安全集合(如 ConcurrentLinkedQueue)。
调用流程总结
with
方法的作用是: (如果是第一次调用)创建Glide对象, 初始化线程池、缓存池、Engine(线程池和缓存池调度的 协调解码,转码和回调任务)、RequestManager(并关联生命周期)- 后续的RequestManager里的load,apply方法的作用是将加载参数放入RequestBuilder中,后续供into中使用
into
方法的作用是:
- into参数最终都变化为DrawableImageViewTarget或BitmapImageViewTarget
- into方法内通过RequstBuilder的buildRequest创建Request对象
- Request作用是缓存请求,并和Target进行关联
- RequestManager: track追踪请求,协调Request和Target, 在适当的时机释放资源
- Glide引擎加载资源的核心方法engine.load(),负责协调内存缓存、磁盘缓存和资源生成
- 如果缓存未命中:
*- 创建新任务(EnginJob) 管理任务状态、处理线程调度、协调多个回调
-
- 创建DecodeJob(资源加载/解码转码任务):负责协调 数据获取、解码、转码、缓存 等关键流程。它的作用可以概括为:将原始数据源(如 URL、File 等)转换为目标可用的资源(如 Bitmap、Drawable)
-
- 通过cb(ResourseCallback)回调resource资源(主线程)