Glide原理

1. 请求启动与构建流程(源码级解析)

    调用链:Glide.with(context).load(url).into(imageView)

(1) Glide.with(context) 初始化

    生命周期绑定:根据 context 类型(Activity/Fragment/Application)创建隐藏的 SupportRequestManagerFragment,通过 RequestManagerRetriever 获取 RequestManager

// RequestManagerRetriever.java
public RequestManager get(Context context) {
    if (context == null) return getApplicationManager(context);
    if (context instanceof Activity) {
        return get((Activity) context);
    } else if (context instanceof FragmentActivity) {
        return get((FragmentActivity) context);
    }
    // ...其他类型处理
}

    作用:将图片加载请求与组件的生命周期(如 onStart, onStop)绑定,避免内存泄漏。

(2) load(url) 构建请求参数

    创建 RequestBuilder,设置数据模型(URL、URI、资源ID等)。

    关键类:RequestManager生成 RequestBuilder,通过泛型指定资源类型。

(3) into(imageView) 发起请求

    步骤分解:

    创建 Target:将 ImageView 包装为 ImageViewTarget(如 BitmapImageViewTarget)。

    构建 Request:通过 RequestBuilder生成 SingleRequest对象。

    执行请求:调用 Request.begin(),进入加载流程。

2. 多级缓存机制(深度解析)

(1) 活动缓存(ActiveResources

    实现类:ActiveResources

    数据结构:Map<Key, ResourceWeakReference>,使用弱引用(WeakReference)持有正在使用的资源。

    回收逻辑:通过 ReferenceQueue 监听弱引用回收,资源不再使用时移入内存缓存。

// ActiveResources.java
void cleanupActiveReference(@NonNull ResourceWeakReference ref) {
    EngineResource<?> removed = activeEngineResources.remove(ref.key);
    if (removed != null) {
        removed.setResourceListener(null);
        cache.put(removed); // 移入内存缓存
    }
}

(2) 内存缓存(MemoryCache)

    默认实现:LruResourceCache(基于LRU算法的LinkedHashMap)。

    缓存键(Key):由 EngineKey 生成,包含URL、尺寸、解码器、变换等参数。

// EngineKey.java
public boolean equals(Object o) {
    if (o instanceof EngineKey) {
        EngineKey other = (EngineKey) o;
        return model.equals(other.model) 
            && signature.equals(other.signature)
            && width == other.width 
            && height == other.height;
    }
    return false;
}

(3) 磁盘缓存(DiskCache)

    策略:分为 DATA(原始数据)和 RESOURCE(处理后的数据)。

    写入流程:通过 DiskLruCacheWrapper 实现,使用LRU算法管理文件。

// DiskLruCacheWrapper.java
public void put(Key key, Writer writer) {
    String safeKey = safeKeyGenerator.getSafeKey(key);
    diskLruCache.edit(safeKey).set(0, writer);
}

3. Bitmap 复用机制(BitmapPool)

(1) 实现原理

    核心类:LruBitmapPool

    数据结构:按 Bitmap 的尺寸和配置(ARGB_8888等)分组存储,使用 TreeMapHashMap 管理。

    复用逻辑:查找尺寸大于等于需求且配置匹配的 Bitmap,调用 reconfigure() 调整尺寸。

// LruBitmapPool.java
public synchronized Bitmap get(int width, int height, Bitmap.Config config) {
    Bitmap result = strategy.get(width, height, config);
    if (result == null) {
        result = createBitmap(width, height, config);
    }
    return result;
}

(2) 避免 GC 压力

    直接内存分配:通过 Bitmap.createBitmap()inBitmap 参数复用内存(需API 11+)。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inMutable = true;
options.inBitmap = reusableBitmap; // 复用内存
Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);

4. 解码与转码流程(详细步骤)

(1) 解码链(DecodePath)

    注册机制:Glide 通过 Registry 注册多个 ResourceDecoder

// Registry.java
public Registry add(Class<T> dataClass, Class<R> resourceClass, ResourceDecoder<T, R> decoder) {
    decoderRegistry.append(dataClass, resourceClass, decoder);
    return this;
}

    匹配流程:按优先级选择第一个可处理数据类型的 Decoder

(2) 转码(Transcode)

    作用:将解码后的资源转换为目标类型(如 Bitmap → Drawable)。

    核心接口:ResourceTranscoder<Z, R>

// BitmapDrawableTranscoder.java
public Resource<BitmapDrawable> transcode(Resource<Bitmap> toTranscode) {
    return new BitmapDrawableResource(new BitmapDrawable(context.getResources(), toTranscode.get()));
}

5. 线程池与并发模型(源码配置)

(1) 线程池类型与参数

线程池名称 核心线程数 队列类型 用途
sourceExecutor 核心数+1 PriorityBlockingQueue 加载原始数据(网络/文件)
diskCacheExecutor 1 FIFO队列 磁盘缓存读写
animationExecutor 2 LinkedBlockingQueue GIF 帧解码

(2) 任务调度逻辑

    磁盘缓存任务:由 diskCacheExecutor 单线程执行,避免并发读写冲突。

    网络请求:通过 sourceExecutor 执行,支持并发但限制最大线程数。

6. 生命周期管理(源码级实现)

(1) 隐式 Fragment 机制

    创建 Fragment:在 RequestManagerRetriever 中为 Activity 添加无UI的 Fragment

// RequestManagerRetriever.java
private SupportRequestManagerFragment getSupportRequestManagerFragment(
    final FragmentManager fm) {
    SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
        current = new SupportRequestManagerFragment();
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
    }
    return current;
}

(2) 生命周期回调

    绑定 RequestManager:Fragment 的生命周期事件传递给 RequestManager

// SupportRequestManagerFragment.java
@Override
public void onStart() {
    super.onStart();
    requestManager.onStart();
}

7. 自定义扩展(高级用法示例)

(1) 自定义 ModelLoader

    目标:加载自定义协议(如 asset://image.png)。

public class AssetModelLoader implements ModelLoader<String, InputStream> {
    @Override
    public LoadData<InputStream> buildLoadData(String model, int width, int height) {
        return new LoadData<>(new ObjectKey(model), new AssetDataFetcher(model));
    }
}

(2) 注册自定义组件

    通过 GlideModule:在 AppGlideModule 中注册。

@GlideModule
public class MyAppGlideModule extends AppGlideModule {
    @Override
    public void registerComponents(Context context, Glide glide, Registry registry) {
        registry.append(String.class, InputStream.class, new AssetModelLoader.Factory());
    }
}

总结:Glide 的极致优化设计

    内存管理:通过三级缓存 + BitmapPool 减少内存分配和GC。

    线程模型:多线程池分工,确保主线程流畅。

    生命周期感知:自动管理请求生命周期,避免泄漏。

    高效解码:灵活的 Decoder/Transcoder 链支持多种数据源。

    高度可扩展:允许深度定制各组件(缓存、加载、解码等)。

    通过以上机制,Glide 在 性能 和 易用性 上达到平衡,成为 Android 图片加载的事实标准。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言 1. Glide 基本用法 接下来的讲解将基于 Glide 目前的最新版本 4.11。 Glide 的使用特...
    灯不利多阅读 2,381评论 0 3
  • Glide分析 发展到现在Android的图片加载框架越来越成熟从一开始的UIL到后来的Glide、Picasso...
    Jesse_zhao阅读 6,196评论 1 8
  • Glide是一个优秀的图片加载库,它有如下优点: Glide可以监听Activity的生命周期管理,更加合理的管理...
    Ihesong阅读 3,443评论 1 5
  • 1.Glide是什么? Glide是Google在2014的IO大会发布一款图片处理框架,是目前android领域...
    无语_4c3f阅读 3,269评论 0 4
  • Glide Glide.with(this).load(url).into(imageView); 三步走:先wi...
    z_q47阅读 573评论 0 0