结合实例一步步讲解Glide关键源码文件的重要知识点

2025-03-06 17:10 结合实例一步步讲解Glide关键源码文件的重要知识点已关闭评论

以下是一个结合实例的 Glide 3.7.0 关键源码文件解析,通过代码片段和流程分析,帮助理解其核心机制。


1. Glide.java:全局入口与初始化

核心作用:配置全局参数、注册组件(解码器、加载器等),提供单例入口。

关键代码分析

public class Glide {
    private static volatile Glide glide; // 单例模式

    // 初始化入口
    public static Glide get(Context context) {
        if (glide == null) {
            synchronized (Glide.class) {
                if (glide == null) {
                    Context applicationContext = context.getApplicationContext();
                    // 通过 GeneratedAppGlideModule 初始化(如应用自定义的 GlideModule)
                    glide = new GlideBuilder().build(applicationContext);
                }
            }
        }
        return glide;
    }

    // 构建 Glide 实例
    Glide build(Context context) {
        // 初始化线程池、注册默认组件(如 BitmapDecoder)
        Engine engine = new Engine(
            memoryCache, 
            diskCacheFactory, 
            diskCacheExecutor, 
            sourceExecutor
        );
        registry = new Registry();
        // 注册默认组件:例如 ImageViewTarget 用于绑定到 ImageView
        registry.register(ImageViewTarget.class, new ImageViewTargetFactory());
        // 加载 GlideModule 配置(通过注解处理器生成)
        GeneratedAppGlideModule module = getAnnotationGeneratedAppGlideModule();
        if (module != null) {
            module.applyOptions(context, new GlideBuilder());
        }
        return new Glide(context, engine, registry);
    }
}

实例分析

  • 自定义 GlideModule

    @GlideModule
    public class MyAppGlideModule extends AppGlideModule {
        @Override
        public void applyOptions(Context context, GlideBuilder builder) {
            // 配置磁盘缓存大小
            builder.setDiskCache(new InternalCacheDiskCacheFactory(context, 100 * 1024 * 1024));
            // 替换网络层为 OkHttp
            builder.setRegistry(registry -> registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory()));
        }
    }
    
    • Glide 初始化时会通过反射找到 @GlideModule 注解的类,并调用 applyOptions

2. RequestManager.java:生命周期管理与请求控制

核心作用:绑定 Activity/Fragment 生命周期,管理请求的启动、暂停、销毁。

关键代码分析

public class RequestManager implements LifecycleListener {
    private final RequestTracker requestTracker = new RequestTracker();
    private final Lifecycle lifecycle;

    // 绑定生命周期
    public void onStart() {
        resumeRequests(); // 恢复请求
    }

    public void onStop() {
        pauseRequests(); // 暂停请求
    }

    public void onDestroy() {
        requestTracker.clearRequests(); // 销毁所有请求
    }

    // 发起请求的入口
    public RequestBuilder<Drawable> load(String url) {
        return asDrawable().load(url);
    }
}

实例分析

  • 生命周期绑定

    // 在 Activity 中绑定
    public class MainActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // Glide 通过 RequestManagerRetriever 获取 RequestManager
            RequestManager requestManager = Glide.with(this);
            requestManager.load("http://example.com/image.jpg").into(imageView);
        }
    }
    
    • Glide.with(Activity) 会通过 RequestManagerRetriever 创建一个与 Activity 生命周期绑定的 RequestManager

3. Engine.java:资源加载引擎

核心作用:协调缓存、线程池、资源加载,是加载流程的核心调度者。

关键代码分析

public class Engine implements EngineJobListener {
    // 核心方法:触发资源加载
    public <R> LoadStatus load(...) {
        // 1. 生成缓存 Key(基于 URL、尺寸、签名等参数)
        EngineKey key = keyFactory.buildKey(model, width, height, transformations);

        // 2. 检查活动缓存(Active Resources)
        EngineResource<?> active = loadFromActiveResources(key);
        if (active != null) {
            return new LoadStatus(cb, active);
        }

        // 3. 检查内存缓存(Memory Cache)
        EngineResource<?> cached = loadFromCache(key);
        if (cached != null) {
            return new LoadStatus(cb, cached);
        }

        // 4. 未命中缓存,创建 EngineJob 和 DecodeJob
        EngineJob<R> engineJob = engineJobFactory.build(...);
        DecodeJob<R> decodeJob = decodeJobFactory.build(...);
        jobs.put(key, engineJob);
        engineJob.addCallback(cb);
        engineJob.start(decodeJob);
    }
}

实例分析

  • 缓存命中流程
    1. 当加载图片时,Engine 首先通过 EngineKey 检查活动缓存(弱引用)。
    2. 如果未命中,再检查 LRU 内存缓存。
    3. 若仍未命中,最终创建 DecodeJob 从磁盘或网络加载。

4. DecodeJob.java:解码任务调度

核心作用:负责数据获取、解码、转码,通过状态机管理任务流程。

关键代码分析

class DecodeJob<R> implements Runnable {
    private DataFetcher<?> fetcher;
    private ResourceDecoder<?, ?> decoder;

    public void run() {
        try {
            // 状态机驱动流程
            runWrapped();
        } catch (Exception e) {
            onLoadFailed(e);
        }
    }

    private void runWrapped() {
        switch (runReason) {
            case INITIALIZE:
                // 确定数据来源:缓存(RESOURCE_CACHE/DATA_CACHE)或原始数据(SOURCE)
                stage = getNextStage(Stage.INITIALIZE);
                currentGenerator = getNextGenerator();
                runGenerators();
                break;
            case SWITCH_TO_SOURCE_SERVICE:
                runGenerators(); // 切换到 SourceExecutor 执行网络请求
                break;
        }
    }

    // 实际加载数据的方法
    private void runGenerators() {
        while (!isCancelled && currentGenerator.startNext()) {
            // 通过 DataFetcher 获取数据(例如 OkHttp 请求)
            // 获取到数据后,通过 ResourceDecoder 解码
        }
    }
}

实例分析

  • 网络图片加载流程
    1. DecodeJob 根据 Stage 判断需要从网络加载(SOURCE)。
    2. 使用 HttpUrlFetcher(默认)或自定义的 OkHttpStreamFetcher 发起网络请求。
    3. 获取到 InputStream 后,通过 BitmapDecoder 解码为 Bitmap。

5. LruResourceCache.java:内存缓存实现

核心作用:基于 LRU 算法管理内存中的图片资源。

关键代码分析

public class LruResourceCache extends LruCache<Key, Resource<?>> implements MemoryCache {
    @Override
    protected int getSize(Resource<?> item) {
        // 计算 Bitmap 占用的内存大小
        return item.getSize();
    }

    @Override
    public void trimMemory(int level) {
        // 根据系统内存压力调整缓存大小
        if (level >= android.content.ComponentCallbacks2.TRIM_MEMORY_MODERATE) {
            clearMemory();
        }
    }
}

实例分析

  • 内存缓存策略
    • 默认最大内存为设备可用内存的 1/8。
    • 当 Activity 销毁时,关联的图片资源会从活动缓存移入内存缓存。

6. DiskLruCacheWrapper.java:磁盘缓存实现

核心作用:基于 LRU 和文件锁管理磁盘缓存。

关键代码分析

public class DiskLruCacheWrapper implements DiskCache {
    private final DiskLruCache diskLruCache;

    @Override
    public File get(Key key) {
        String safeKey = safeKeyGenerator.getSafeKey(key);
        // 生成缓存文件名(例如 "image_url_1234_0")
        File file = new File(directory, safeKey + ".0");
        return file.exists() ? file : null;
    }

    @Override
    public void put(Key key, Writer writer) {
        // 写入磁盘(通过 FileLocks 防止并发冲突)
        DiskLruCache.Editor editor = diskLruCache.edit(safeKey);
        OutputStream os = editor.newOutputStream(0);
        writer.write(os); // 写入数据(如 Bitmap 压缩后的字节流)
        editor.commit();
    }
}

实例分析

  • 磁盘缓存文件结构
    • 缓存目录:/data/data/com.example.app/cache/image_manager_disk_cache
    • 文件名:通过 URL、尺寸等参数生成的哈希值(如 a1b2c3d4.0)。

总结:Glide 源码执行流程

  1. 初始化Glide.java 配置全局参数,注册组件。
  2. 请求发起RequestManager.load(url) 绑定生命周期。
  3. 缓存检查Engine 检查活动缓存、内存缓存、磁盘缓存。
  4. 数据加载:未命中缓存时,DecodeJob 调度网络请求或文件读取。
  5. 解码与转码ResourceDecoderTranscoder 处理数据。
  6. 资源交付:通过 Target 在主线程更新 UI。

通过分析关键源码文件,可以深入理解 Glide 的模块化设计、缓存策略和线程模型。调试时可结合日志(adb shell setprop log.tag.Glide VERBOSE)观察缓存命中与加载流程。

当前文章价值6.9元,扫一扫支付后添加微信提供帮助!(如不能解决您的问题,可以申请退款)

你可能感兴趣的文章

来源:每日教程每日一例,深入学习实用技术教程,关注公众号TeachCourse
转载请注明出处: https://teachcourse.cn/3774.html ,谢谢支持!

资源分享

Eclipse手动安装SVN插件操作 Eclipse手动安装SVN插件操作
python库pyQt所有布局及用法示例介绍 python库pyQt所有布局及用法示例
Python内置关键字详细用法(3) Python内置关键字详细用法(3)
100个python小工具001:文件重命名 100个python小工具001:文件重命

评论已关闭!