Glide 4.x 版本的图片加载流程

结合 Glide 的源码(基于 Glide 4.x 版本,因为这是目前最广泛使用的版本)详细讲解图片加载的完整流程。Glide 是一个高效、灵活的图片加载库,其核心在于异步加载、缓存管理和资源优化。以下是图片加载流程的详细分解,涵盖关键源码和实现原理。


1. Glide 初始化与请求起点

图片加载的起点是调用 Glide.with(context),这是 Glide 的入口方法,用于创建加载请求的上下文环境。

源码分析:Glide.with()

java 复制代码
public static RequestManager with(@NonNull Context context) {
    return getRetriever(context).get(context);
}
  • 作用Glide.with() 获取或创建一个 RequestManager 实例,RequestManager 是管理图片加载请求的核心类。
  • 实现细节
    • getRetriever(context) 返回一个 RequestManagerRetriever,负责管理 RequestManager 的生命周期。
    • 根据传入的 context 类型(ActivityFragmentApplication),Glide 会绑定生命周期(如 Activity 的 onDestroy),确保资源在适当时候释放。
    • 如果是 Application 上下文,Glide 使用一个无生命周期的 RequestManager,适合全局加载。

关键点

  • Glide 使用 FragmentSupportRequestManagerFragmentRequestManagerFragment)来监听 Activity/Fragment 的生命周期,确保加载请求在组件销毁时暂停或取消。
  • 源码中,RequestManager 内部维护了一个 RequestTracker,用于跟踪和管理所有请求。

2. 构建请求:load() 和配置

调用 Glide.with(context).load(url) 开始构建加载请求。load() 方法接收图片资源(如 URL、文件路径、资源 ID 等)。

源码分析:load()

java 复制代码
public RequestBuilder<Drawable> load(@Nullable String string) {
    return asDrawable().load(string);
}
  • 作用load() 返回一个 RequestBuilder 实例,用于配置加载请求的参数(如占位图、错误图、变换等)。
  • 实现细节
    • asDrawable() 指定加载的目标资源类型(默认是 Drawable,也可以是 BitmapGif)。
    • load(String) 将图片的 URI 或路径存储到 RequestBuilder 中,供后续处理。

配置选项

开发者可以通过链式调用配置加载选项,例如:

java 复制代码
Glide.with(context)
    .load(url)
    .placeholder(R.drawable.placeholder)
    .error(R.drawable.error)
    .thumbnail(0.25f)
    .diskCacheStrategy(DiskCacheStrategy.ALL)
    .into(imageView);
  • 这些配置会存储在 RequestBuilder 和底层的 RequestOptions 中,影响加载流程的各个阶段。

3. 触发加载:into()

调用 into(ImageView) 是触发图片加载的最终步骤,Glide 在此将请求提交到后台线程执行。

源码分析:into()

java 复制代码
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    // 构建 Target
    ViewTarget<ImageView, TranscodeType> target = buildImageViewTarget(view, transcodeClass);
    // 提交请求
    return into(target);
}
  • 作用into() 创建一个 ViewTarget(通常是 ImageViewTarget),并将加载任务提交给 Glide 的执行引擎。
  • 实现细节
    • buildImageViewTarget 根据目标类型(DrawableBitmap)创建相应的 Target
    • into(Target) 调用 RequestBuilder.into(Target),启动加载流程。

关键点

  • Target 是 Glide 中用于接收加载结果的接口,ImageViewTarget 负责将加载的图片设置到 ImageView 上。
  • into() 内部,Glide 会检查 ImageView 的当前状态(如尺寸),并根据需要延迟加载(等待布局完成)。

4. 请求执行:Engine 核心

RequestBuilder.into() 最终将请求交给 Engine 类,Engine 是 Glide 的核心调度器,负责管理加载任务和缓存。

源码分析:Engine.load()

java 复制代码
public <R> LoadStatus load(
    GlideContext glideContext,
    Object model,
    Key signature,
    int width,
    int height,
    Class<?> resourceClass,
    Class<R> transcodeClass,
    Priority priority,
    DiskCacheStrategy diskCacheStrategy,
    Map<Class<?>, Transformation<?>> transformations,
    boolean isMemoryCacheable,
    boolean useUnlimitedSourceExecutor,
    boolean useAnimationPool,
    boolean onlyRetrieveFromCache,
    Options options,
    EngineJobListener callback) {
    // 检查缓存
    EngineResource<?> cached = memoryCache.get(key);
    if (cached != null) {
        callback.onResourceReady(cached);
        return null;
    }
    // 创建 EngineJob
    EngineJob<R> engineJob = engineJobFactory.build(...);
    // 提交到线程池
    engineJob.start(decodeJob);
}
  • 作用Engine.load() 负责检查缓存、创建加载任务并提交到线程池。
  • 实现细节
    1. 缓存检查
      • 首先检查内存缓存(memoryCache),如果命中,直接返回缓存资源。
      • 如果未命中,检查磁盘缓存(DiskLruCache)或发起网络请求。
    2. 任务创建
      • 创建 EngineJob,负责协调加载任务的执行。
      • 创建 DecodeJob,负责实际的资源解码和处理。
    3. 线程池提交
      • 根据优先级(Priority)和配置,任务被提交到 sourceExecutor(网络加载)或 diskCacheExecutor(缓存加载)。

5. 资源获取与解码:DecodeJob

DecodeJob 是执行图片加载和解码的核心类,负责从缓存或网络获取资源并进行解码。

源码分析:DecodeJob.run()

java 复制代码
void run() {
    try {
        if (onlyRetrieveFromCache) {
            resource = decodeFromCache();
        } else {
            resource = decodeFromRetriever();
        }
    } catch (Throwable t) {
        notifyFailed(t);
    }
}
  • 作用DecodeJob 根据配置决定从缓存还是网络加载资源。
  • 实现细节
    1. 缓存加载decodeFromCache):
      • 检查磁盘缓存(DiskLruCache),如果命中,调用 DataFetcher 解码数据。
      • 磁盘缓存使用 LRU 算法,存储原始数据或转换后的资源。
    2. 网络加载decodeFromRetriever):
      • 使用 DataFetcher(如 HttpUrlFetcher)从网络获取数据。
      • 数据流通过 InputStream 传递给解码器(如 BitmapDecoderGifDecoder)。
    3. 解码与转换
      • 解码后,资源可能经过 Transformation(如圆角、裁剪)处理。
      • 最终生成 BitmapDrawableGifDrawable

6. 缓存管理

Glide 的缓存机制是其高效性的关键,分为内存缓存和磁盘缓存。

内存缓存

  • 使用 LruResourceCache(基于 LRU 算法的内存缓存)存储加载完成的资源。

  • ActiveResources 存储正在使用的资源,防止被 GC 回收。

  • 源码:

    java 复制代码
    memoryCache.put(key, resource);

磁盘缓存

  • 使用 DiskLruCache 存储原始数据或转换后的资源。

  • 配置通过 DiskCacheStrategy 控制(如 ALLDATARESOURCE)。

  • 源码:

    java 复制代码
    diskCache.put(key, writer);

7. 结果回调与显示

加载完成后,EngineJob 通过回调将结果传递给 Target

源码分析:EngineJob.onResourceReady()

java 复制代码
void onResourceReady(Resource<R> resource, DataSource dataSource) {
    mainThreadCallback.onResourceReady(resource, dataSource);
}
  • 作用 :将加载的资源传递到主线程,调用 Target.onResourceReady()
  • 实现细节
    • ImageViewTarget 接收资源并调用 setImageDrawable()setImageBitmap()
    • 如果配置了占位图或错误图,Glide 会根据加载状态显示相应图片。

8. 生命周期管理

Glide 通过 RequestManager 绑定生命周期,确保资源管理高效:

  • 当 Activity/Fragment 暂停时,RequestManager.pauseRequests() 暂停所有请求。
  • 当销毁时,RequestManager.clearRequests() 取消所有请求并释放资源。

源码分析:RequestManager.onStart()

java 复制代码
public void onStart() {
    resumeRequests();
}

总结:Glide 图片加载流程

  1. 初始化Glide.with() 创建 RequestManager,绑定生命周期。 GPR
  2. 请求构建load() 和配置选项(如 placeholderdiskCacheStrategy)生成 RequestBuilder
  3. 触发加载into() 创建 Target 并提交请求。
  4. 任务调度Engine 检查缓存,创建 EngineJobDecodeJob
  5. 资源获取DecodeJob 从缓存或网络加载数据,解码并应用转换。
  6. 缓存管理 :内存缓存(LruResourceCache)和磁盘缓存(DiskLruCache)优化性能。
  7. 结果显示 :资源通过 Target 显示到 ImageView
  8. 生命周期:绑定组件生命周期,自动暂停/取消请求。

关键优化与设计亮点

  • 三级缓存 :内存缓存(LruResourceCacheActiveResources)、磁盘缓存(DiskLruCache)、网络加载。
  • 线程池管理 :使用 ExecutorService 区分网络和磁盘任务,优化并发。
  • 资源复用 :通过 BitmapPool 复用 Bitmap,减少内存分配。
  • 模块化设计DataFetcherDecoderTransformation 解耦,支持扩展。
相关推荐
面朝大海,春不暖,花不开23 分钟前
自定义Spring Boot Starter的全面指南
java·spring boot·后端
得过且过的勇者y24 分钟前
Java安全点safepoint
java
夜晚回家1 小时前
「Java基本语法」代码格式与注释规范
java·开发语言
斯普信云原生组1 小时前
Docker构建自定义的镜像
java·spring cloud·docker
wangjinjin1801 小时前
使用 IntelliJ IDEA 安装通义灵码(TONGYI Lingma)插件,进行后端 Java Spring Boot 项目的用户用例生成及常见问题处理
java·spring boot·intellij-idea
wtg44521 小时前
使用 Rest-Assured 和 TestNG 进行购物车功能的 API 自动化测试
java
白宇横流学长2 小时前
基于SpringBoot实现的大创管理系统设计与实现【源码+文档】
java·spring boot·后端
fat house cat_2 小时前
【redis】线程IO模型
java·redis
stein_java3 小时前
springMVC-10验证及国际化
java·spring
weixin_478689763 小时前
C++ 对 C 的兼容性
java·c语言·c++