Glide系列(一) — Glide 框架结构浅析

Glide 框架结构浅析

    • 一、概述
    • 二、Glide 框架整体结构设计
    • 三、DataLoadProvider、ModelLoader、DataFetcher 之间的关系
    • 四、LoadProvider
      • 1. 子类 FixLoadProvider
      • 2. 子类 ChildLoadProvider
      • 3. 小结

一、概述

Glide 是一个图片加载库,跟它同类型的库还有 Picasso、Fresco、Universal-Image-Loader 等。

本文主要从以下几个角度来分析 Glide:

  1. 分析 Glide 到整体结构设计 (分层设计、缓存设计)。
  2. 分析 DataLoadProvider、ModelLoader、DataFetcher 的作用及它们之间的关系。
  3. 分析 LoadProvider 到作用。

Glide 框架的优点:

  1. 加载类型多样化:Glide 支持 Gif、WebP 等格式的图片。
  2. 生命周期的绑定:图片请求与页面生命周期绑定,避免内存泄漏。
  3. 使用简单(链式调用),且提供丰富的 Api 功能 (如: 图片裁剪等功能)。
  4. 高效的缓存策略:
    1. 支持多种缓存策略 (Memory 和 Disk 图片缓存)。
    2. 根据 ImageView 的大小来加载相应大小的图片尺寸。
    3. 内存开销小,默认使用 RGB_565 格式 (3.x 版本)。
    4. 使用 BitmapPool 进行 Bitmap 的复用。

本系列采用 Glide3.7.0 版本,从以下几个角度来进行分析。

  1. Glide系列(一) — Glide 框架结构浅析
  2. Glide系列(二) — Glide 注册模块分析
  3. Glide系列(三) — Request 构建流程分析
  4. Glide系列(四) — Glide 缓存获取流程分析
  5. Glide系列(五) — 如何实现 Request 生命周期管理
  6. Glide系列(六) — 如何实现原图和缩略图 Request 的协同
  7. Glide系列(七) — Glide 面试
  8. Glide系列(八) — Glide4.11.0 缓存获取的流程分析

注: 目前 Glide 版本已经更新到 4.11.0,但本系列我们仍采用 Glide3.7.0 版本进行分析,原因有两个:
(a) 3.7.0 版本代码相对比较简单。
(b) 与 3.7.0 版本相比,4.0+ 版本之后代码改动较大。
所以本着先易后难的原则,我们使用 Glide 3.7.0 来进行分析,对 Glide 整体有一个全面了解之后,再去分析 4.0+ 版本。


Glide 版本: Glide 3.7.0
Github 地址: https://github.com/bumptech/glide/tree/v3.7.0
Gradle 依赖: implementation 'com.github.bumptech.glide:glide:3.7.0'


二、Glide 框架整体结构设计

Glide系列(一) — Glide 框架结构浅析_第1张图片

Glide 框架结构如上图所示:

  1. Glide 框架主要分为两大流程:
    1.1 图片请求的构建流程
    1.2 图片缓存的获取流程
  2. 图片请求构建流程内又分为四个模块:
    2.1 用户态的请求模块: 用户使用 Glide 进行链式调用的时候会生成一个用户态的 Request。
    2.2 真实的请求模块: 由于步骤2.1中会根据场景构建多种Request,因此在发起图片请求时需要进行收口,因此会使用用户态的 Request 构建一个真正的 GenericRequest 请求。
    2.3 Request 生命周期管理模块: Glide 的一大特点是会将图片的请求和页面生命周期进行绑定,避免出现内存泄漏的风险,因此会有一个 Request 生命周期管理模块。
    2.4 Registry中心模块: 由于 Glide 支持加载多种类型的数据,因此在注册中心会预先注册所支持类型处理类的信息。
  3. 图片缓存一共分为3大层,5小层:
    3.1 内存缓存(2小层): 弱引用缓存、LruCache。
    3.2 本地缓存(2小层): 本地 Result 缓存、本地 Source 缓存。
    3.3 Source 数据源(1小层): 网络获取、本地 AssetPath 获取、其它本地图片。

小结:

看到这里,只要知道以下三点就可以了。

  1. 知道 Glide 分为两大流程 (请求创建流程、缓存获取流程) 就可以了。
  2. 知道 Glide 缓存部分分为3大层,5小层就可以了。
  3. 可以将 Glide 的两大流程与网络请求进行类比。网络请求也分为两个流程:网络请求的构建流程、数据的接收和响应流程 (Glide的缓存获取流程)。

三、DataLoadProvider、ModelLoader、DataFetcher 之间的关系

在 Glide 中,有几个比较重要的接口类,它们之间的关系如下图所示。
Glide系列(一) — Glide 框架结构浅析_第2张图片
上图涉及的几个类含义如下:

  1. DataLoadProvider: 提供特定类型的编/解码器的类,从它的抽象方法就可以看出。
  2. LoadProvider: 用于将 ModelLoaderResourceTranscoder 进行关联 (相当于将编解码功能、数据获取功能、数据类型转换功能都聚合在一个 Provider 上,便于操作)。
  3. ModelLoader: ModelLoader 是与支持的加载类型相匹配的,返回能够加载指定类型数据的 DataFetcher。
  4. ResourceTranscoder: 类型转换器 (如: 将 Resource 转换成 Resource 类型)。
  5. DataFetcher: 具体加载数据的类 (如: 从网络上加载图片数据)。
  6. Encoder: 用于将原始数据写入Disk缓存。
  7. ResoutceEncoder: 用于将 decoded 和 transformed 之后的资源写入 Disk 缓存。
  8. ResoutceDecoder: 用于将原始数据或者是Disk缓存数据进行解码,解析成可以使用的格式。

小结: 看到这里,需要了解如下信息。

  1. DataLoadProvider 内持有处理图片相关的编/解码器。
  2. LoadProvider 是一个聚合类,继承自 DataLoadProvider 接口,因此具备提供编解码器的能力,同时聚合了 ModelLoader 和 ResourceTranscoder。
  3. ModelLoader 会根据提供的加载类型返回一个相应的 DataFetcher。

四、LoadProvider

在第三部分,我们分析了 DataLoadProvider、ModelLoader、DataFetcher 之间的关系,知道了 LoadProvider 是一个聚合类,下面我们来具体分析一下。

LoadProvider 类的关系图如下:
Glide系列(一) — Glide 框架结构浅析_第3张图片

LoadProvider 有两个子类:FixLoadProviderChildLoadProvider

1. 子类 FixLoadProvider

FixLoadProvider

public class FixedLoadProvider<A, T, Z, R> implements LoadProvider<A, T, Z, R>  {
    private final ModelLoader<A, T> modelLoader;
    private final ResourceTranscoder<Z, R> transcoder;
    private final DataLoadProvider<T, Z> dataLoadProvider;

    public FixedLoadProvider(ModelLoader<A, T> modelLoader, ResourceTranscoder<Z, R> transcoder,
            DataLoadProvider<T, Z> dataLoadProvider) {
        this.modelLoader = modelLoader;
        this.transcoder = transcoder;
        this.dataLoadProvider = dataLoadProvider;
    }
}

小结:

FixLoadProvider 是一个聚合类,持有 ModelLoader、ResourceTranscoder、DataLoadProvider 对象的引用,具备提供 DataFetcher、图片编/解码器、图片转码 的功能。

2. 子类 ChildLoadProvider

public class ChildLoadProvider<A, T, Z, R> implements LoadProvider<A, T, Z, R>, Cloneable {
    private final LoadProvider<A, T, Z, R> parent;

    private ResourceDecoder<File, Z> cacheDecoder;

    public ChildLoadProvider(LoadProvider<A, T, Z, R> parent) {
        this.parent = parent;
    }
    @Override
    public ModelLoader<A, T> getModelLoader() {
        return parent.getModelLoader();
    }
    
    public void setCacheDecoder(ResourceDecoder<File, Z> cacheDecoder) {
        this.cacheDecoder = cacheDecoder;
    }
    
    @Override
    public ResourceDecoder<File, Z> getCacheDecoder() {
        if (cacheDecoder != null) {
            return cacheDecoder;
        } else {
            return parent.getCacheDecoder();
        }
    }
}

小结:

ChildLoadProvider 内持有一个 LoadProvider 引用,相关的操作都是通过这个 LoadProvider 引用进行操作,同时提供了对 编解码器 进行赋值的 Api。

3. 小结

FixLoadProvider 和 ChildLoadProvider 构成了一个装饰者模式。其中 ChildLoadProvider 是 Decorator 角色,他提供设置 编/解码器的功能。

为什么要这么设计?

默认情况下 FixLoadProvider 是自动创建的,不支持用户设置自定义的ResourceTranscoder 以及编/解码器。而通过装饰者模式可以对原有的 FixLoadProvider 功能进行增强,使之具备这个功能。


下一篇文章我们先来分析一下 《Glide 注册模块分析》 ,这有助于分析 Glide加载流程。

你可能感兴趣的:(开源框架源码分析)