简体中文简体中文
EnglishEnglish
简体中文简体中文

深入解析Glide的源码:揭秘图片加载框架的内部

2025-01-20 19:10:47

随着移动互联网的快速发展,图片加载框架在Android开发中扮演着越来越重要的角色。Glide作为当前最受欢迎的图片加载库之一,其简洁的API和高效的性能赢得了广大开发者的青睐。本文将深入解析Glide的源码,带您了解这个强大框架的内部机制。

一、Glide简介

Glide是一个开源的图片加载库,由Bilibili团队开发。它支持GIF、WebP、视频等格式的图片加载,具有以下特点:

1.简洁的API:Glide提供了一套简单易用的API,开发者可以轻松实现图片的加载、缓存、转换等功能。 2.高效的缓存机制:Glide采用LRU缓存策略,有效提高图片加载速度。 3.异步加载:Glide支持异步加载图片,不会阻塞主线程。 4.支持图片转换:Glide支持对图片进行裁剪、缩放、旋转等转换操作。

二、Glide源码解析

1.Glide初始化

在Android项目中,首先需要在build.gradle文件中添加Glide依赖:

java dependencies { implementation 'com.github.bumptech.glide:glide:4.12.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' }

接着,在Application中初始化Glide:

java public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); Glide.get(this).init(new GlideBuilder(this) .setDiskCache(new InternalDiskCacheFactory(getCacheDir(), 1024 * 1024 * 50)) .setMemoryCache(new LruResourceCache(20)) .setLogLevel(Log.ERROR)); } }

这里,我们设置了磁盘缓存大小为50MB,内存缓存大小为20个对象,并设置了日志级别为ERROR。

2.图片加载流程

当调用Glide.with(context).load(url).into(imageView)方法时,Glide会按照以下流程加载图片:

(1)检查内存缓存:首先,Glide会检查内存缓存中是否已存在该图片资源。如果存在,则直接从内存缓存中获取并显示。

(2)检查磁盘缓存:如果内存缓存中没有该图片资源,Glide会检查磁盘缓存。如果磁盘缓存中有,则从磁盘缓存中读取并加载到内存缓存中。

(3)下载图片:如果磁盘缓存中也没有该图片资源,Glide会从网络下载图片。下载完成后,将图片存储到磁盘缓存和内存缓存中。

(4)显示图片:最后,Glide将图片显示到ImageView上。

3.图片转换

Glide支持对图片进行裁剪、缩放、旋转等转换操作。以下是图片转换的源码解析:

`java RequestBuilder<Drawable> transform(DrawableTransformation transformation) { return applyOptions(new TransformationRequest<>(this, transformation)); }

private RequestBuilder<Drawable> applyOptions(TransformationRequest<Drawable> request) { if (this.transformations.isEmpty()) { return this; } RequestBuilder<Drawable> builder = this; for (Transformation<Drawable> t : this.transformations) { builder = builder.transform(t); } return builder.transform(request); } `

这里,Glide通过链式调用transform()方法添加图片转换,然后通过applyOptions()方法将转换应用到图片加载请求中。

4.异步加载

Glide采用异步加载图片,不会阻塞主线程。以下是异步加载的源码解析:

`java public void into(ImageView imageView) { if (imageView == null) { throw new IllegalArgumentException("You cannot pass null for imageView"); } if (this.model == null) { throw new IllegalArgumentException("You must not pass in null for model"); } if (this.placeholder == null && this.errorPlaceholder == null) { throw new IllegalArgumentException("You must pass in either a placeholder or an error placeholder."); } if (this.placeholderRes == 0 && this.errorPlaceholderRes == 0) { throw new IllegalArgumentException("You must pass in either a placeholder resource id or an error placeholder resource id."); } if (this.transformation == null) { throw new IllegalArgumentException("You must not pass in null for transformation"); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE) { throw new IllegalArgumentException("You cannot use DiskCacheStrategy.NONE with a custom DiskCacheFactory."); } if (this.decoder == null) { throw new IllegalArgumentException("You must not pass in null for decoder"); } if (this.sourceEncoder == null) { throw new IllegalArgumentException("You must not pass in null for sourceEncoder"); } if (this.decoderCacheKey == null) { throw new IllegalArgumentException("You must not pass in null for decoderCacheKey"); } if (this.diskCacheWriter == null) { throw new IllegalArgumentException("You must not pass in null for diskCacheWriter"); } if (this.sourceKey == null) { throw new IllegalArgumentException("You must not pass in null for sourceKey"); } if (this.sourceEncoderCacheKey == null) { throw new IllegalArgumentException("You must not pass in null for sourceEncoderCacheKey"); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCache == null) { throw new IllegalArgumentException("You cannot use DiskCacheStrategy.NONE with a null DiskCache."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheExecutor == null) { throw new IllegalArgumentException("You cannot use DiskCacheStrategy.NONE with a null diskCacheExecutor."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheLoader == null) { throw new IllegalArgumentException("You cannot use DiskCacheStrategy.NONE with a null diskCacheLoader."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.isEmpty()) { throw new IllegalArgumentException("You cannot use DiskCacheStrategy.NONE with an empty list of diskCacheTransformations."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 1) { throw new IllegalArgumentException("You cannot use more than one diskCacheTransformation with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0) == null) { throw new IllegalArgumentException("You cannot use a null diskCacheTransformation with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationRequired()) { throw new IllegalArgumentException("You cannot use a Transformation that requires transformation with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithCrossOrigin()) { throw new IllegalArgumentException("You cannot use a Transformation that requires crossOrigin with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithGif()) { throw new IllegalArgumentException("You cannot use a Transformation that requires gif with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithVideo()) { throw new IllegalArgumentException("You cannot use a Transformation that requires video with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithImageDecoder()) { throw new IllegalArgumentException("You cannot use a Transformation that requires imageDecoder with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoder()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoder with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size() > 0 && this.diskCacheTransformations.get(0).isTransformationWithSourceEncoderCacheKey()) { throw new IllegalArgumentException("You cannot use a Transformation that requires sourceEncoderCacheKey with DiskCacheStrategy.NONE."); } if (this.diskCacheStrategy == DiskCacheStrategy.NONE && this.diskCacheTransformations.size()