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的架构设计体现了几个核心原则:
- 模块化:各组件分工明确,易于扩展和定制
- 资源优化:通过精细的内存管理和缓存机制提高性能
- API友好:流畅的链式API设计使用简单直观
- 生命周期感知:与Android组件生命周期集成,避免内存泄漏
- 可扩展性:通过Registry系统支持自定义组件注册
这种优雅的架构设计使Glide能够高效处理图片加载、转换和缓存,同时保持API的简洁性和可扩展性,堪称Android图片加载库架构设计的典范。
Notes
本文分析基于Glide源码,着重解析了Glide的核心架构组件和设计模式。还有更多细节如线程池管理、优先级处理等未能完全展开,有兴趣的读者可以进一步深入研究源码。