Android Glide 配置与初始化模块源码深度剖析

112 阅读13分钟

一、整体概述

在 Android 开发中,图片加载是一个常见且重要的功能。Glide 作为一款强大的图片加载库,因其高效、灵活和易于使用的特点,被广泛应用于各种 Android 应用中。Glide 的配置与初始化模块是整个库的基础,它允许开发者根据不同的需求对 Glide 进行定制化设置,如缓存策略、图片解码格式、自定义组件等。本文将深入 Glide 源码,详细剖析其配置与初始化模块的实现原理和工作流程。

二、配置与初始化模块概述

2.1 模块的作用

Glide 的配置与初始化模块主要负责以下几个方面的工作:

  • 全局配置:允许开发者对 Glide 的各种行为进行全局配置,如设置缓存大小、自定义组件等。
  • 组件注册:开发者可以通过该模块注册自定义的组件,如 ModelLoaderResourceDecoder 等,以支持新的数据源和图片格式。
  • 生命周期管理:确保 Glide 与应用的生命周期进行正确的绑定,避免内存泄漏。

2.2 核心组件

该模块的核心组件包括:

  • GlideBuilder:用于构建 Glide 实例,提供了一系列方法来设置 Glide 的各种配置。
  • GlideModule(在 Glide 4.x 及以后版本为 AppGlideModule 和 LibraryGlideModule):提供了一种在应用启动时配置 Glide 的方式,开发者可以在 GlideModule 中注册自定义的组件、修改默认配置等。
  • Glide:Glide 库的核心类,负责管理图片加载请求、缓存、线程池等。

2.3 整体架构

Glide 配置与初始化模块的整体架构可以分为以下几个层次:

  1. 应用层:开发者在应用代码中调用 Glide 的初始化方法,并进行相关配置。
  2. 配置层GlideBuilder 和 GlideModule 负责接收开发者的配置信息,并进行相应的设置。
  3. 核心层Glide 类根据配置信息进行初始化,创建各种组件和服务。

三、GlideBuilder 源码分析

3.1 类定义及属性

java

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.Glide;
import com.bumptech.glide.Registry;
import com.bumptech.glide.load.DecodeFormat;
import com.bumptech.glide.load.engine.Engine;
import com.bumptech.glide.load.engine.cache.DiskCache;
import com.bumptech.glide.load.engine.cache.DiskCacheFactory;
import com.bumptech.glide.load.engine.cache.MemoryCache;
import com.bumptech.glide.load.engine.cache.M.cache.MemorySizeCalculator;
import com.bumptech.glide.load.engine.executor.GlideExecutor;
import com.bumptech.glide.manager.ConnectivityMonitorFactory;
import com.bumptech.glide.manager.DefaultConnectivityMonitorFactory;
import com.bumptech.glide.manager.Lifecycle;
import com.bumptech.glide.manager.RequestManagerRetriever;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.ViewTarget;
import com.bumptech.glide.util.Preconditions;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;

// GlideBuilder 类,用于构建 Glide 实例
public final class GlideBuilder {
    // 应用上下文
    private final Context context;
    // 内存缓存工厂
    private MemoryCache.Factory memoryCacheFactory;
    // 磁盘缓存工厂
    private DiskCache.Factory diskCacheFactory;
    // 引擎工厂
    private Engine.Factory engineFactory;
    // 解码格式
    private DecodeFormat decodeFormat = DecodeFormat.DEFAULT;
    // 默认的请求选项
    private RequestOptions defaultRequestOptions = new RequestOptions();
    // 连接监控工厂
    private ConnectivityMonitorFactory connectivityMonitorFactory;
    // 后台线程池
    private GlideExecutor sourceExecutor;
    // 磁盘缓存线程池
    private GlideExecutor diskCacheExecutor;
    // 动画帧线程池
    private GlideExecutor animationExecutor;
    // 生命周期
    private Lifecycle lifecycle;
    // 请求管理器检索器
    private RequestManagerRetriever.RequestManagerFactory requestManagerFactory;
    // 视图目标的默认布局参数
    private ViewTarget.LayoutParamsFactory defaultLayoutParamsFactory;
    // 注册表,用于注册各种组件
    private final Registry registry = new Registry();
    // 全局日志级别
    private int logLevel = android.util.Log.DEBUG;
    // 动画处理类
    private Handler mainHandler;
    // 内存大小计算器
    private MemorySizeCalculator memorySizeCalculator;
    // 组件清单解析器
    private final List<com.bumptech.glide.module.GlideModule> manifestModules = new ArrayList<>();
    // 自定义的 Glide 模块
    private com.bumptech.glide.module.GlideModule customModule;
}

在 GlideBuilder 类中,定义了一系列属性,用于存储 Glide 的各种配置信息。这些属性包括内存缓存工厂、磁盘缓存工厂、引擎工厂、解码格式、默认请求选项等。通过这些属性,开发者可以对 Glide 的各个方面进行定制化配置。

3.2 构造函数

java

/**
 * 构造函数,初始化 GlideBuilder 实例
 * 
 * @param context 应用上下文
 */
GlideBuilder(@NonNull Context context) {
    // 保存应用上下文
    this.context = context.getApplicationContext();
}

构造函数接收一个 Context 对象,并将其转换为应用上下文进行保存。这是为了避免因传入的 Context 生命周期过短而导致的内存泄漏问题。

3.3 配置方法

3.3.1 内存缓存配置

java

/**
 * 设置内存缓存工厂
 * 
 * @param memoryCacheFactory 内存缓存工厂
 * @return GlideBuilder 实例,用于链式调用
 */
@NonNull
public GlideBuilder setMemoryCache(@NonNull MemoryCache.Factory memoryCacheFactory) {
    // 检查传入的内存缓存工厂是否为空
    this.memoryCacheFactory = Preconditions.checkNotNull(memoryCacheFactory);
    return this;
}

setMemoryCache 方法用于设置内存缓存工厂。开发者可以通过该方法自定义内存缓存的实现,例如使用自定义的 LruResourceCache 或其他内存缓存策略。

3.3.2 磁盘缓存配置

java

/**
 * 设置磁盘缓存工厂
 * 
 * @param diskCacheFactory 磁盘缓存工厂
 * @return GlideBuilder 实例,用于链式调用
 */
@NonNull
public GlideBuilder setDiskCache(@NonNull DiskCache.Factory diskCacheFactory) {
    // 检查传入的磁盘缓存工厂是否为空
    this.diskCacheFactory = Preconditions.checkNotNull(diskCacheFactory);
    return this;
}

setDiskCache 方法用于设置磁盘缓存工厂。开发者可以通过该方法自定义磁盘缓存的实现,例如使用自定义的 DiskLruCacheWrapper 或其他磁盘缓存策略。

3.3.3 引擎配置

java

/**
 * 设置引擎工厂
 * 
 * @param engineFactory 引擎工厂
 * @return GlideBuilder 实例,用于链式调用
 */
@NonNull
public GlideBuilder setEngine(@NonNull Engine.Factory engineFactory) {
    // 检查传入的引擎工厂是否为空
    this.engineFactory = Preconditions.checkNotNull(engineFactory);
    return this;
}

setEngine 方法用于设置引擎工厂。引擎是 Glide 的核心组件之一,负责管理图片的加载、缓存和资源回收等操作。开发者可以通过该方法自定义引擎的实现。

3.3.4 解码格式配置

java

/**
 * 设置解码格式
 * 
 * @param decodeFormat 解码格式
 * @return GlideBuilder 实例,用于链式调用
 */
@NonNull
public GlideBuilder setDecodeFormat(@NonNull DecodeFormat decodeFormat) {
    // 检查传入的解码格式是否为空
    this.decodeFormat = Preconditions.checkNotNull(decodeFormat);
    return this;
}

setDecodeFormat 方法用于设置图片的解码格式。不同的解码格式会影响图片的质量和内存占用,开发者可以根据实际需求选择合适的解码格式。

3.3.5 默认请求选项配置

java

/**
 * 设置默认的请求选项
 * 
 * @param defaultRequestOptions 默认请求选项
 * @return GlideBuilder 实例,用于链式调用
 */
@NonNull
public GlideBuilder setDefaultRequestOptions(@NonNull RequestOptions defaultRequestOptions) {
    // 检查传入的默认请求选项是否为空
    this.defaultRequestOptions = Preconditions.checkNotNull(defaultRequestOptions);
    return this;
}

setDefaultRequestOptions 方法用于设置默认的请求选项。默认请求选项会应用到所有的图片加载请求中,开发者可以通过该方法设置一些通用的请求参数,如占位图、错误图等。

3.3.6 连接监控工厂配置

java

/**
 * 设置连接监控工厂
 * 
 * @param factory 连接监控工厂
 * @return GlideBuilder 实例,用于链式调用
 */
@NonNull
public GlideBuilder setConnectivityMonitorFactory(@NonNull ConnectivityMonitorFactory factory) {
    // 检查传入的连接监控工厂是否为空
    this.connectivityMonitorFactory = Preconditions.checkNotNull(factory);
    return this;
}

setConnectivityMonitorFactory 方法用于设置连接监控工厂。连接监控工厂用于创建连接监控器,监控网络连接状态的变化,以便在网络连接可用时自动恢复图片加载任务。

3.3.7 线程池配置

java

/**
 * 设置后台线程池
 * 
 * @param sourceExecutor 后台线程池
 * @return GlideBuilder 实例,用于链式调用
 */
@NonNull
public GlideBuilder setSourceExecutor(@NonNull GlideExecutor sourceExecutor) {
    // 检查传入的后台线程池是否为空
    this.sourceExecutor = Preconditions.checkNotNull(sourceExecutor);
    return this;
}

/**
 * 设置磁盘缓存线程池
 * 
 * @param diskCacheExecutor 磁盘缓存线程池
 * @return GlideBuilder 实例,用于链式调用
 */
@NonNull
public GlideBuilder setDiskCacheExecutor(@NonNull GlideExecutor diskCacheExecutor) {
    // 检查传入的磁盘缓存线程池是否为空
    this.diskCacheExecutor = Preconditions.checkNotNull(diskCacheExecutor);
    return this;
}

/**
 * 设置动画帧线程池
 * 
 * @param animationExecutor 动画帧线程池
 * @return GlideBuilder 实例,用于链式调用
 */
@NonNull
public GlideBuilder setAnimationExecutor(@NonNull GlideExecutor animationExecutor) {
    // 检查传入的动画帧线程池是否为空
    this.animationExecutor = Preconditions.checkNotNull(animationExecutor);
    return this;
}

这些方法分别用于设置后台线程池、磁盘缓存线程池和动画帧线程池。不同的线程池用于执行不同类型的任务,如后台线程池用于执行网络请求和图片解码任务,磁盘缓存线程池用于执行磁盘缓存的读写任务,动画帧线程池用于执行动画帧的加载和处理任务。

3.3.8 其他配置方法

java

/**
 * 设置生命周期
 * 
 * @param lifecycle 生命周期
 * @return GlideBuilder 实例,用于链式调用
 */
@NonNull
public GlideBuilder setLifecycle(@NonNull Lifecycle lifecycle) {
    // 检查传入的生命周期是否为空
    this.lifecycle = Preconditions.checkNotNull(lifecycle);
    return this;
}

/**
 * 设置请求管理器工厂
 * 
 * @param factory 请求管理器工厂
 * @return GlideBuilder 实例,用于链式调用
 */
@NonNull
public GlideBuilder setRequestManagerFactory(@NonNull RequestManagerRetriever.RequestManagerFactory factory) {
    // 检查传入的请求管理器工厂是否为空
    this.requestManagerFactory = Preconditions.checkNotNull(factory);
    return this;
}

/**
 * 设置视图目标的默认布局参数工厂
 * 
 * @param factory 视图目标的默认布局参数工厂
 * @return GlideBuilder 实例,用于链式调用
 */
@NonNull
public GlideBuilder setDefaultLayoutParamsFactory(@NonNull ViewTarget.LayoutParamsFactory factory) {
    // 检查传入的视图目标的默认布局参数工厂是否为空
    this.defaultLayoutParamsFactory = Preconditions.checkNotNull(factory);
    return this;
}

/**
 * 设置全局日志级别
 * 
 * @param logLevel 全局日志级别
 * @return GlideBuilder 实例,用于链式调用
 */
@NonNull
public GlideBuilder setLogLevel(int logLevel) {
    this.logLevel = logLevel;
    return this;
}

/**
 * 设置动画处理类
 * 
 * @param mainHandler 动画处理类
 * @return GlideBuilder 实例,用于链式调用
 */
@NonNull
public GlideBuilder setMainHandler(@NonNull Handler mainHandler) {
    // 检查传入的动画处理类是否为空
    this.mainHandler = Preconditions.checkNotNull(mainHandler);
    return this;
}

这些方法分别用于设置生命周期、请求管理器工厂、视图目标的默认布局参数工厂、全局日志级别和动画处理类。开发者可以通过这些方法对 Glide 的各个方面进行更细致的配置。

3.4 构建 Glide 实例

java

/**
 * 构建 Glide 实例
 * 
 * @return Glide 实例
 */
@NonNull
public Glide build(@NonNull Context context) {
    // 如果未设置后台线程池,使用默认的后台线程池
    if (sourceExecutor == null) {
        sourceExecutor = GlideExecutor.newSourceExecutor();
    }
    // 如果未设置磁盘缓存线程池,使用默认的磁盘缓存线程池
    if (diskCacheExecutor == null) {
        diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
    }
    // 如果未设置动画帧线程池,使用默认的动画帧线程池
    if (animationExecutor == null) {
        animationExecutor = GlideExecutor.newAnimationExecutor();
    }

    // 如果未设置内存大小计算器,创建一个默认的内存大小计算器
    if (memorySizeCalculator == null) {
        memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
    }

    // 如果未设置内存缓存工厂,使用默认的内存缓存工厂
    if (memoryCacheFactory == null) {
        memoryCacheFactory = new LruResourceCache.Factory(memorySizeCalculator.getMemoryCacheSize());
    }

    // 如果未设置磁盘缓存工厂,使用默认的磁盘缓存工厂
    if (diskCacheFactory == null) {
        diskCacheFactory = new InternalCacheDiskCacheFactory(context);
    }

    // 如果未设置引擎工厂,使用默认的引擎工厂
    if (engineFactory == null) {
        engineFactory = new Engine.Factory(diskCacheFactory, diskCacheExecutor, sourceExecutor);
    }

    // 如果未设置连接监控工厂,使用默认的连接监控工厂
    if (connectivityMonitorFactory == null) {
        connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
    }

    // 如果未设置动画处理类,创建一个默认的动画处理类
    if (mainHandler == null) {
        mainHandler = new Handler(Looper.getMainLooper());
    }

    // 创建引擎实例
    Engine engine = engineFactory.build(
            memoryCacheFactory.build(),
            diskCacheExecutor,
            sourceExecutor,
            animationExecutor,
            isActiveResourceRetentionAllowed);

    // 创建请求管理器检索器
    RequestManagerRetriever requestManagerRetriever = new RequestManagerRetriever(requestManagerFactory);

    // 创建 Glide 实例
    Glide glide = new Glide(
            context,
            engine,
            memoryCacheFactory.build(),
            diskCacheFactory,
            registry,
            animationExecutor,
            memorySizeCalculator,
            connectivityMonitorFactory,
            logLevel,
            defaultRequestOptions.lock(),
            defaultTransitionOptions,
            requestManagerRetriever,
            mainHandler,
            defaultLayoutParamsFactory);

    // 注册所有的 Glide 模块
    for (com.bumptech.glide.module.GlideModule module : manifestModules) {
        module.registerComponents(context, glide, registry);
    }
    if (customModule != null) {
        customModule.registerComponents(context, glide, registry);
    }

    return glide;
}

build 方法用于构建 Glide 实例。在该方法中,会检查各个配置项是否已经设置,如果未设置,则使用默认的配置。然后根据配置信息创建引擎、请求管理器检索器等组件,并最终创建 Glide 实例。最后,会注册所有的 GlideModule,以便对 Glide 进行进一步的配置和扩展。

四、GlideModule 源码分析

4.1 GlideModule 概述

在 Glide 4.x 及以后版本中,GlideModule 被拆分为 AppGlideModule 和 LibraryGlideModuleAppGlideModule 用于在应用级别进行配置,而 LibraryGlideModule 用于在库级别进行配置。

4.2 AppGlideModule 源码分析

4.2.1 类定义及属性

java

import android.content.Context;
import androidx.annotation.NonNull;
import com.bumptech.glide.Glide;
import com.bumptech.glide.Registry;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.AppGlideModule;

// 标记该类为 AppGlideModule
@GlideModule
public class MyAppGlideModule extends AppGlideModule {
    // 可以在这里添加自定义的配置方法和属性
}

AppGlideModule 是一个抽象类,开发者需要创建一个继承自 AppGlideModule 的子类,并使用 @GlideModule 注解进行标记。

4.2.2 主要方法

java

@Override
public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
    // 在这里可以对 GlideBuilder 进行配置
    builder.setMemoryCache(new LruResourceCache(10 * 1024 * 1024)); // 设置内存缓存大小为 10MB
    builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, 50 * 1024 * 1024)); // 设置磁盘缓存大小为 50MB
}

@Override
public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
    // 在这里可以注册自定义的组件
    registry.append(MyModel.class, InputStream.class, new MyModelLoader.Factory());
}

@Override
public boolean isManifestParsingEnabled() {
    // 是否启用组件清单解析
    return false;
}
  • applyOptions 方法:用于对 GlideBuilder 进行配置,开发者可以在该方法中设置内存缓存、磁盘缓存、解码格式等配置信息。
  • registerComponents 方法:用于注册自定义的组件,如 ModelLoaderResourceDecoder 等。通过该方法,开发者可以扩展 Glide 的功能,支持新的数据源和图片格式。
  • isManifestParsingEnabled 方法:用于控制是否启用组件清单解析。在 Glide 4.x 及以后版本中,建议将该方法返回 false,以避免组件清单解析带来的性能开销。

4.3 LibraryGlideModule 源码分析

4.3.1 类定义及属性

java

import android.content.Context;
import androidx.annotation.NonNull;
import com.bumptech.glide.Glide;
import com.bumptech.glide.Registry;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.LibraryGlideModule;

// 标记该类为 LibraryGlideModule
@GlideModule
public class MyLibraryGlideModule extends LibraryGlideModule {
    // 可以在这里添加自定义的配置方法和属性
}

LibraryGlideModule 也是一个抽象类,开发者需要创建一个继承自 LibraryGlideModule 的子类,并使用 @GlideModule 注解进行标记。

4.3.2 主要方法

java

@Override
public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
    // 在这里可以注册自定义的组件
    registry.append(MyModel.class, InputStream.class, new MyModelLoader.Factory());
}

LibraryGlideModule 主要用于在库级别注册自定义的组件。与 AppGlideModule 不同的是,LibraryGlideModule 没有 applyOptions 方法,因为库级别通常不进行全局配置,而是专注于组件的注册。

五、Glide 初始化流程分析

5.1 初始化入口

在应用代码中,通常通过以下方式初始化 Glide:

java

GlideBuilder builder = new GlideBuilder(context);
Glide glide = builder.build(context);

或者使用 Glide.get(context) 方法,该方法会在内部调用 GlideBuilder 进行初始化:

java

Glide glide = Glide.get(context);

5.2 初始化流程

  1. 创建 GlideBuilder 实例:在初始化过程中,首先会创建一个 GlideBuilder 实例,用于接收和保存配置信息。
  2. 配置 GlideBuilder:开发者可以通过 GlideBuilder 的各种配置方法,对 Glide 的内存缓存、磁盘缓存、引擎、解码格式等进行配置。
  3. 注册 GlideModule:在 build 方法中,会注册所有的 GlideModule,包括 AppGlideModule 和 LibraryGlideModule。在 GlideModule 中,开发者可以对 GlideBuilder 进行进一步的配置,或者注册自定义的组件。
  4. 创建核心组件:根据配置信息,build 方法会创建引擎、请求管理器检索器等核心组件。
  5. 创建 Glide 实例:最后,build 方法会创建 Glide 实例,并将配置信息和核心组件传递给 Glide 实例。

5.3 初始化流程的源码分析

java

// Glide 类中的 get 方法
public static Glide get(@NonNull Context context) {
    // 检查传入的上下文是否为空
    if (glide == null) {
        synchronized (Glide.class) {
            if (glide == null) {
                // 获取应用上下文
                Context applicationContext = context.getApplicationContext();
                // 获取组件清单解析器
                List<com.bumptech.glide.module.GlideModule> manifestModules = new ManifestParser(applicationContext).parse();
                // 创建 GlideBuilder 实例
                GlideBuilder builder = new GlideBuilder(applicationContext);
                // 创建 AppGlideModule 实例
                AppGlideModule appGlideModule = new GeneratedAppGlideModuleImpl();
                // 应用 AppGlideModule 中的配置
                appGlideModule.applyOptions(applicationContext, builder);
                // 注册 LibraryGlideModule 中的组件
                for (com.bumptech.glide.module.GlideModule module : manifestModules) {
                    module.registerComponents(applicationContext, builder, builder.getRegistry());
                }
                // 注册 AppGlideModule 中的组件
                appGlideModule.registerComponents(applicationContext, builder, builder.getRegistry());
                // 构建 Glide 实例
                glide = builder.build(applicationContext);
            }
        }
    }
    return glide;
}

在 get 方法中,会首先检查 Glide 实例是否已经创建。如果未创建,则会进行以下操作:

  1. 获取应用上下文。
  2. 使用 ManifestParser 解析组件清单,获取所有的 LibraryGlideModule
  3. 创建 GlideBuilder 实例。
  4. 创建 AppGlideModule 实例,并调用其 applyOptions 方法对 GlideBuilder 进行配置。
  5. 注册所有 LibraryGlideModule 和 AppGlideModule 中的组件。
  6. 调用 GlideBuilder 的 build 方法构建 Glide 实例。

六、自定义配置和组件注册

6.1 自定义内存缓存

开发者可以通过 GlideBuilder 的 setMemoryCache 方法自定义内存缓存。以下是一个自定义内存缓存的示例:

java

// 自定义内存缓存工厂
class MyMemoryCacheFactory implements MemoryCache.Factory {
    @Override
    public MemoryCache build() {
        return new LruResourceCache(20 * 1024 * 1024); // 设置内存缓存大小为 20MB
    }
}

// 在应用代码中使用自定义内存缓存
GlideBuilder builder = new GlideBuilder(context);
builder.setMemoryCache(new MyMemoryCacheFactory());
Glide glide = builder.build(context);

在这个示例中,我们创建了一个自定义的内存缓存工厂 MyMemoryCacheFactory,并在 build 方法中返回一个 LruResourceCache 实例,设置其大小为 20MB。然后通过 GlideBuilder 的 setMemoryCache 方法使用该自定义内存缓存工厂。

6.2 自定义磁盘缓存

开发者可以通过 GlideBuilder 的 setDiskCache 方法自定义磁盘缓存。以下是一个自定义磁盘缓存的示例:

java

// 自定义磁盘缓存工厂
class MyDiskCacheFactory implements DiskCache.Factory {
    @Override
    public DiskCache build() {
        return DiskLruCacheWrapper.create(new File(context.getExternalCacheDir(), "my_cache"),