文章目录
- 一、前言
- 二、源码分析
- 1、load()
Android Glide图片加载框架系列文章
Android Glide图片加载框架(一)基本用法
Android Glide图片加载框架(二)源码解析之with()
Android Glide图片加载框架(二)源码解析之load()
Android Glide图片加载框架(二)源码解析之into()
Android Glide图片加载框架(三)缓存机制
一、前言
在源码分析系列文章中,上一篇我们分析了 Glide.with()
方法的用法及作用,它传递了我们的上下文对象,并且返回绑定了对应生命周期的RequestManager对象,还没有看过上一篇文章的朋友,建议先去阅读 Android Glide图片加载框架(二)源码解析之with()。
下面我们来详细分析 load()
方法的源码。
二、源码分析
1、load()
我们先来回顾下,平时在使用load方法的时候,可以传入很多不同的参数,例如:
Glide.with(this).load(R.drawable.ic_android).into(imageView);
Glide.with(this).load("http://xxx.xxx.png").into(imageView);
Glide.with(this).load(Uri.parse("xxxxx")).into(imageView);
Glide.with(this).load(getResources().getDrawable(R.drawable.ic_android)).into(imageView);
Glide.with(this).load(new File("xxx")).into(imageView);
Glide.with(this).load(BitmapFactory.decodeFile("xxx")).into(imageView);
从上述代码中我们可以看到有很多个 load()
方法的重载,支持了多种形式的图片资源,包括 本地图片
、应用资源
、网络图片
、二进制流
、Uri对象
等,使用起来很方便,不用再自己写一堆请求网络或者读取本地文件的骚操作,那么Glide的load()里面对它们做了什么处理,能够兼容这么多形式的加载呢,让我们一探究竟。
上一篇我们分析了 with()
方法的源码,由于 with()
方法返回的是一个 RequestManager
对象,那么很容易就能想到,load()
方法是在 RequestManager
类当中的,所以说我们首先要看的就是 RequestManager
这个类。
RequestManager
类的简化代码(我们以load(String);为例)如下所示:
public class RequestManager implements LifecycleListener,ModelTypes<RequestBuilder<Drawable>> {...@NonNull@CheckResult@Overridepublic RequestBuilder<Drawable> load(@Nullable String string) {return asDrawable().load(string);}@NonNull@CheckResultpublic RequestBuilder<Drawable> asDrawable() {return as(Drawable.class);}@NonNull@CheckResultpublic <ResourceType> RequestBuilder<ResourceType> as(@NonNull Class<ResourceType> resourceClass) {return new RequestBuilder<>(glide, this, resourceClass, context);}...
}
RequestManager
类的代码是非常多的,但是经过我这样简化之后,看上去就比较清爽了。在我们只探究加载图片URL字符串这一个load()方法的情况下,那么比较重要的方法就只剩下上述代码中的这三个方法。
那么我们先来看 load()
方法,这个方法中的逻辑是非常简单的,只有一行代码,就是先调用了 asDrawable()
方法,而 asDrawable()
方法也极为简单,就是调用了 as()
方法,并且指定参数为 Drawable.class
,as()方法中初始化了一个 RequestBuilder
对象,然后调用 RequestBuilder对象的load()
方法。
细心的朋友会发现,Glide不止有 asDrawable()
,其实还有 asBitmap()
、asGif()
、asFile()
等等,如下:
public class RequestManager implements LifecycleListener,ModelTypes<RequestBuilder<Drawable>> {...public RequestBuilder<Bitmap> asBitmap() {return as(Bitmap.class).apply(DECODE_TYPE_BITMAP);}public RequestBuilder<GifDrawable> asGif() {return as(GifDrawable.class).apply(DECODE_TYPE_GIF);}public RequestBuilder<File> asFile() {return as(File.class).apply(skipMemoryCacheOf(true));}public <ResourceType> RequestBuilder<ResourceType> as(@NonNull Class<ResourceType> resourceClass) {return new RequestBuilder<>(glide, this, resourceClass, context);}...
}
由此我们可以发现,Glide默认使用的是 asDrawable() ,不管是还有 asBitmap()
、asGif()
还是 asFile()
最终都调用 as()
方法返回 RequestBuilder
对象实例。
RequestBuilder类的简化代码如下所示:
public class RequestBuilder<TranscodeType> implements Cloneable,ModelTypes<RequestBuilder<TranscodeType>> {protected RequestBuilder(Glide glide, RequestManager requestManager,Class<TranscodeType> transcodeClass, Context context) {this.glide = glide;this.requestManager = requestManager;this.transcodeClass = transcodeClass;this.defaultRequestOptions = requestManager.getDefaultRequestOptions();this.context = context;this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass);this.requestOptions = defaultRequestOptions;this.glideContext = glide.getGlideContext();}@NonNull@Override@CheckResultpublic RequestBuilder<TranscodeType> load(@Nullable String string) {return loadGeneric(string);}@NonNullprivate RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {this.model = model;isModelSet = true;return this;}
}
从 RequestBuilder
的构造方法中我们可以看到,这里的 transcodeClass
就是我们刚传进来的Drawable类型,成为了 RequestBuilder
的成员变量。RequestBuilder对象实例化后,调用RequestBuilder的 load()
方法,load()方法内部都是调用了 loadGeneric()
,这里的 model
即传进来的资源参数(例如String、Bitmap、File…),同样赋给RequestBuilder的成员变量,并且置 isModelSet
标志位为true,即标志着设置完成的意思,并且将这个RequestBuilder实例返回。
至此我们得到了关于 RequestBuilder参数
的一些信息:
-
transcodeClass:
表示要将最终结果转换为什么类型; -
model:
表示传进来的资源参数; -
isModelSet:
是为了标志你已经调用了load方法,是一个必要条件,否则你没有先设置你所要加载的资源,Glide怎么知道你要加载啥。
至此,Glide的 load()
完成了它的使命,是不是有种被欺骗的感觉,load()方法其实还没真正开始加载,into()才是最终加载的地方
。