Glide 整体架构之美赏析

Glide是一个高效、灵活的Android图片加载库,其架构设计精巧,层次分明。本文将对Glide的整体架构进行详细分析。

1. 总体架构概览

Glide采用了模块化设计,核心组件通过注册表(Registry)进行管理,使用流畅的链式API创建请求,并由Engine引擎处理资源加载和缓存管理。整个框架遵循单例模式、构建者模式和工厂模式等设计模式。

复制代码
Glide  
   ├── RequestManager - 管理生命周期和请求  
   ├── Registry - 组件注册管理  
   ├── Engine - 加载和缓存处理引擎  
   ├── DecodeJob - 解码工作  
   └── BitmapPool/MemoryCache - 资源管理  

2. 核心组件解析

2.1 Glide单例

Glide通过静态单例模式提供整个应用程序的一致入口点:

less 复制代码
public static Glide get(@NonNull Context context) {  
  if (glide == null) {  
    GeneratedAppGlideModule annotationGeneratedModule =  
        getAnnotationGeneratedGlideModules(context.getApplicationContext());  
    synchronized (Glide.class) {  
      if (glide == null) {  
        checkAndInitializeGlide(context, annotationGeneratedModule);  
      }  
    }  
  }  
  return glide;  
}

Glide类负责创建和管理所有主要组件,包括BitmapPool、MemoryCache、Registry等:

less 复制代码
Glide(  
    @NonNull Context context,  
    @NonNull Engine engine,  
    @NonNull MemoryCache memoryCache,  
    @NonNull BitmapPool bitmapPool,  
    @NonNull ArrayPool arrayPool,  
    @NonNull RequestManagerRetriever requestManagerRetriever,  
    @NonNull ConnectivityMonitorFactory connectivityMonitorFactory,  
    int logLevel,  
    @NonNull RequestOptionsFactory defaultRequestOptionsFactory,  
    @NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions,  
    @NonNull List<RequestListener<Object>> defaultRequestListeners,  
    @NonNull List<GlideModule> manifestModules,  
    @Nullable AppGlideModule annotationGeneratedModule,  
    @NonNull GlideExperiments experiments) {  
  this.engine = engine;  
  this.bitmapPool = bitmapPool;  
  this.arrayPool = arrayPool;  
  this.memoryCache = memoryCache;  
  this.requestManagerRetriever = requestManagerRetriever;  
  this.connectivityMonitorFactory = connectivityMonitorFactory;  
  this.defaultRequestOptionsFactory = defaultRequestOptionsFactory;

2.2 组件注册系统

Glide使用Registry来管理所有可扩展组件,包括解码器、转换器等。RegistryFactory负责创建和初始化Registry:

java 复制代码
static GlideSupplier<Registry> lazilyCreateAndInitializeRegistry(  
    final Glide glide,  
    final List<GlideModule> manifestModules,  
    @Nullable final AppGlideModule annotationGeneratedModule) {  
  return new GlideSupplier<Registry>() {  
    // Rely on callers using memoization if they want to avoid duplicate work, but  
    // rely on ourselves to verify that no recursive initialization occurs.  
    private boolean isInitializing;  
  
    @Override  
    public Registry get() {  
      if (isInitializing) {  
        throw new IllegalStateException(  
            "Recursive Registry initialization! In your"  
                + " AppGlideModule and LibraryGlideModules, Make sure you're using the provided "  
                + "Registry rather calling glide.getRegistry()!");  
      }  
      Trace.beginSection("Glide registry");  
      isInitializing = true;  
      try {  
        return createAndInitRegistry(glide, manifestModules, annotationGeneratedModule);  
      } finally {  
        isInitializing = false;  
        Trace.endSection();  
      }  
    }  
  };  
}

Registry负责将不同的模型类型、数据类型、资源类型和转码类型连接起来,形成一个完整的加载管道:

typescript 复制代码
private static void initializeDefaults(  
    Context context,  
    Registry registry,  
    BitmapPool bitmapPool,  
    ArrayPool arrayPool,  
    GlideExperiments experiments) {  
  registry.register(new DefaultImageHeaderParser());  
  // Right now we're only using this parser for HEIF images, which are only supported on OMR1+.  
  // If we need this for other file types, we should consider removing this restriction.  
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {  
    registry.register(new ExifInterfaceImageHeaderParser());  
  }

2.3 请求构建系统

RequestBuilder采用流畅的API设计,允许开发者链式设置各种选项:

scala 复制代码
public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>  
    implements Cloneable, ModelTypes<RequestBuilder<TranscodeType>> {  
  // Used in generated subclasses  
  protected static final RequestOptions DOWNLOAD_ONLY_OPTIONS =  
      new RequestOptions()  
          .diskCacheStrategy(DiskCacheStrategy.DATA)  
          .priority(Priority.LOW)  
          .skipMemoryCache(true);  
  
  private final Context context;  
  private final RequestManager requestManager;  
  private final Class<TranscodeType> transcodeClass;  
  private final Glide glide;  
  private final GlideContext glideContext;

2.4 解码与转换系统

Glide的解码工作由DecodeJob完成,它负责协调数据获取、缓存检查和资源解码:

java 复制代码
class DecodeJob<R>  
    implements DataFetcherGenerator.FetcherReadyCallback,  
        Runnable,  
        Comparable<DecodeJob<?>>,  
        Poolable {  
  private static final String TAG = "DecodeJob";  
  
  private final DecodeHelper<R> decodeHelper = new DecodeHelper<>();  
  private final List<Throwable> throwables = new ArrayList<>();  
  private final StateVerifier stateVerifier = StateVerifier.newInstance();  
  private final DiskCacheProvider diskCacheProvider;  
  private final Pools.Pool<DecodeJob<?>> pool;  
  private final DeferredEncodeManager<?> deferredEncodeManager = new DeferredEncodeManager<>();  
  private final ReleaseManager releaseManager = new ReleaseManager();

DecodeJob使用状态机模式,在不同阶段间转换:

csharp 复制代码
private void runWrapped() {  
  switch (runReason) {  
    case INITIALIZE:  
      stage = getNextStage(Stage.INITIALIZE);  
      currentGenerator = getNextGenerator();  
      runGenerators();  
      break;  
    case SWITCH_TO_SOURCE_SERVICE:  
      runGenerators();  
      break;  
    case DECODE_DATA:  
      decodeFromRetrievedData();  
      break;  
    default:  
      throw new IllegalStateException("Unrecognized run reason: " + runReason);  
  }  
}

2.5 图像转换系统

Glide提供了丰富的内置图像转换功能,如剪裁、缩放和圆角处理:

arduino 复制代码
public static Bitmap centerCrop(  
    @NonNull BitmapPool pool, @NonNull Bitmap inBitmap, int width, int height) {  
  if (inBitmap.getWidth() == width && inBitmap.getHeight() == height) {  
    return inBitmap;  
  }  
  // From ImageView/Bitmap.createScaledBitmap.  
  final float scale;  
  final float dx;  
  final float dy;  
  Matrix m = new Matrix();  
  if (inBitmap.getWidth() * height > width * inBitmap.getHeight()) {  
    scale = (float) height / (float) inBitmap.getHeight();  
    dx = (width - inBitmap.getWidth() * scale) * 0.5f;  
    dy = 0;  
  } else {  
    scale = (float) width / (float) inBitmap.getWidth();  
    dx = 0;  
    dy = (height - inBitmap.getHeight() * scale) * 0.5f;  
  }

自定义转换则通过实现BitmapTransformation接口:

ruby 复制代码
/**  
 * A simple {@link com.bumptech.glide.load.Transformation} for transforming {@link  
 * android.graphics.Bitmap}s that abstracts away dealing with {@link  
 * com.bumptech.glide.load.engine.Resource} objects for subclasses.  
 *  
 * <p>Use cases will look something like this:  
 *  
 * <pre>{@code  
 * public class FillSpace extends BitmapTransformation {  
 *     private static final String ID = "com.bumptech.glide.transformations.FillSpace";  
 *     private static final byte[] ID_BYTES = ID.getBytes(Charset.forName("UTF-8"));  
 *  
 *     {@literal @Override}  
 *     public Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {  
 *         if (toTransform.getWidth() == outWidth && toTransform.getHeight() == outHeight) {  
 *             return toTransform;  
 *         }  
 *  
 *         return Bitmap.createScaledBitmap(toTransform, outWidth, outHeight, true);  
 *     }

3. 资源管理

Glide对内存和磁盘资源进行精细管理,包括内存缓存、磁盘缓存和位图池:

scss 复制代码
public void trimMemory(int level) {  
  // Engine asserts this anyway when removing resources, fail faster and consistently  
  Util.assertMainThread();  
  // Request managers need to be trimmed before the caches and pools, in order for the latter to  
  // have the most benefit.  
  synchronized (managers) {  
    for (RequestManager manager : managers) {  
      manager.onTrimMemory(level);  
    }  
  }  
  // memory cache needs to be trimmed before bitmap pool to trim re-pooled Bitmaps too. See #687.  
  memoryCache.trimMemory(level);  
  bitmapPool.trimMemory(level);  
  arrayPool.trimMemory(level);  
}

4. 流式请求API

Glide提供了简洁直观的API,使用链式调用构建图片加载请求:

typescript 复制代码
public static RequestManager with(@NonNull Context context) {  
  return getRetriever(context).get(context);  
}  
  
/**  
 * Begin a load with Glide that will be tied to the given {@link android.app.Activity}'s lifecycle  
 * and that uses the given {@link Activity}'s default options.  
 *  
 * @param activity The activity to use.  
 * @return A RequestManager for the given activity that can be used to start a load.  
 * @deprecated This is equivalent to calling {@link #with(Context)} using the application context.  
 *     Use the androidx Activity class instead (ie {@link FragmentActivity}, or {@link  
 *     androidx.appcompat.app.AppCompatActivity}).  
 */

总结

Glide的架构设计体现了几个核心原则:

  1. 模块化:各组件分工明确,易于扩展和定制
  2. 资源优化:通过精细的内存管理和缓存机制提高性能
  3. API友好:流畅的链式API设计使用简单直观
  4. 生命周期感知:与Android组件生命周期集成,避免内存泄漏
  5. 可扩展性:通过Registry系统支持自定义组件注册

这种优雅的架构设计使Glide能够高效处理图片加载、转换和缓存,同时保持API的简洁性和可扩展性,堪称Android图片加载库架构设计的典范。

Notes

本文分析基于Glide源码,着重解析了Glide的核心架构组件和设计模式。还有更多细节如线程池管理、优先级处理等未能完全展开,有兴趣的读者可以进一步深入研究源码。

相关推荐
独行soc3 分钟前
2025年渗透测试面试题总结-安恒[实习]安全服务工程师(题目+回答)
linux·数据库·安全·web安全·面试·职场和发展·渗透测试
编程乐学(Arfan开发工程师)1 小时前
10、底层注解-@Conditional条件装配
java·spring boot·后端·架构
Sonetto19993 小时前
【Python】【面试凉经】Fastapi为什么Fast
python·面试·flask·fastapi·凉经
无名小组12 小时前
【架构篇】项目架构设计思路
架构
985小水博一枚呀12 小时前
【AI大模型学习路线】第二阶段之RAG基础与架构——第七章(【项目实战】基于RAG的PDF文档助手)技术方案与架构设计?
人工智能·学习·语言模型·架构·大模型
掘金-我是哪吒13 小时前
分布式微服务系统架构第132集:Python大模型,fastapi项目-Jeskson文档-微服务分布式系统架构
分布式·python·微服务·架构·系统架构
冬瓜的编程笔记14 小时前
【八股战神篇】MySQL高频面试题
数据库·mysql·面试
独行soc14 小时前
2025年渗透测试面试题总结-百度面经(题目+回答)
运维·开发语言·经验分享·学习·面试·渗透测试·php
掘金-我是哪吒15 小时前
分布式微服务系统架构第129集:redis安装部署文档
redis·分布式·微服务·架构·系统架构
编程、小哥哥15 小时前
Java大厂面试:从Web框架到微服务技术的场景化提问与解析
java·spring boot·微服务·面试·技术栈·数据库设计·分布式系统