深入解析Glide的源码:揭秘图片加载框架的内部
随着移动互联网的快速发展,图片加载框架在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()