一 源码分析
根据前面即便,想来对Glide源码已经有了初步了解,这篇是最后篇,主要对前面几篇的源码进行总结,从Glide的流式调用来分析:
Glide.with(this).load(url).into(imageView);
1.1 with()
这个方法传入的是上下文context,主要是创建Clide对象和将Glide与传入的context进行生命周期的绑定
1.1.1 重要对象名
1.1.2 具体源码
Glide.java
public class Glide {
...
// with()重载种类非常多,根据传入的参数可分为:
// 1. 非Application类型的参数(Activity & Fragment )
// 2. Application类型的参数(Context)
// 下面将详细分析
// 参数1:Application类型
public static RequestManager with(Context context) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
// 步骤1:调用RequestManagerRetriever类的静态get()获得RequestManagerRetriever对象 - 单例实现
return retriever.get(context);
// 步骤2:调用RequestManagerRetriever实例的get()获取RequestManager对象 & 绑定图片加载的生命周期 ->>分析1
}
// 参数2:非Application类型(Activity & Fragment )
public static RequestManager with(Activity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(activity);
}
public static RequestManager with(Fragment fragment) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(fragment);
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static RequestManager with(android.app.Fragment fragment) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(fragment);
}
}
}
RequestManagerRetriever.java
```java
public class RequestManagerRetriever implements Handler.Callback {
...
// 实例的get()重载种类很多,参数分为:(与with()类似)
// 1. Application类型(Context)
// 2. 非Application类型(Activity & Fragment )- >>分析3
// 下面会详细分析
// 参数1:Application类型(Context)
public RequestManager get(Context context) {
// 调用getApplicationManager()最终获取一个RequestManager对象
// 因为Application对象的生命周期即App的生命周期
// 所以Glide加载图片的生命周期是自动与应用程序的生命周期绑定,不需要做特殊处理(若应用程序关闭,Glide的加载也会终止)
return getApplicationManager(context);
}
// 参数2:非Application类型(Activity & Fragment )
// 将Glide加载图片的生命周期与Activity生命周期同步的具体做法:向当前的Activity添加一个隐藏的Fragment
// 原因:因Fragment的生命周期 与 Activity 的是同步的,通过添加隐藏的Fragment 从而监听Activity的生命周期,从而实现Glide加载图片的生命周期与Activity的生命周期 进行同步。
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public RequestManager get(Activity activity) {
if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
return get(activity.getApplicationContext());
} else {
//判断activity是否已经销毁
assertNotDestroyed(activity);
// 获取FragmentManager 对象
android.app.FragmentManager fm = activity.getFragmentManager();
// 通过fragmentGet返回RequestManager
return fragmentGet(activity, fm); // 分析 1
}
}
public RequestManager get(FragmentActivity activity) {
}
public RequestManager get(Fragment fragment) {
}
}
分析1:
// 作用:
// 1. 创建Fragment
// 2. 向当前的Activity中添加一个隐藏的Fragment
// 3. 将RequestManager与该隐藏的Fragment进行绑定
RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
RequestManagerFragment current = getRequestManagerFragment(fm);
// 获取RequestManagerFragment
// 作用:利用Fragment进行请求的生命周期管理
RequestManager requestManager = current.getRequestManager();
// 若requestManager 为空,即首次加载初始化requestManager
if (requestManager == null) {
// 创建RequestManager传入Lifecycle实现类,如ActivityFragmentLifecycle
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
// 调用setRequestManager设置到RequestManagerFragment
}
return requestManager;
}
private RequestManager getApplicationManager(Context context) {
...
Glide glide = Glide.get(context); // 分析2
// 通过单例模式创建Glide实例
applicationManager =
new RequestManager(
glide, new ApplicationLifecycle(), new EmptyRequestManagerTreeNode());
}
}
}
return applicationManager;
}
分析 2 **Glide.java**
public static Glide get(Context context) {
if (glide == null) {
// 单例模式
synchronized (Glide.class) {
if (glide == null) {
Context applicationContext = context.getApplicationContext();
// 解析清单文件配置的自定义GlideModule的metadata标签,返回一个GlideModule集合
List<GlideModule> modules = new ManifestParser(applicationContext).parse();
// 步骤1:创建GlideBuilder对象
GlideBuilder builder = new GlideBuilder(applicationContext);
for (GlideModule module : modules) {
module.applyOptions(applicationContext, builder);
}
// 步骤2:根据GlideBuilder对象创建Glide实例
// GlideBuilder会为Glide设置一默认配置,如:Engine,RequestOptions,GlideExecutor,MemorySizeCalculator
glide = builder.createGlide();
for (GlideModule module : modules) {
// 步骤3:利用GlideModule 进行延迟性的配置和ModelLoaders的注册
module.registerComponents(applicationContext, glide.registry);
}
}
}
}
return glide;
}
1.1.3 总结
with()方法是为了得到RequestManager对象,而这个对象主要是用来管理Glide请求与上下文的生命周期绑定的,具体生命周期如何绑定,请点击Glide生命周期解析
1.2 load()
此时通过with()方法之后,返回了RequestManager,所以第二部load()其实就是RequestManager的load()方法。
1.2.1 作用
预先创建好对图片的一系列操作(加载,编解码,转码)的对象,并且把这些全部封装到DrawableTypeRequest对象中。
Glide支持的图片加载方式有URL,图片本地路径,资源ID等,因为RequestManager类肯定存在load()的多个重载方法,这里我们就只分析最常见的URL字符串的加载方式,即load(String url)
1.2.2 具体源码
RequestManager.java
public class RequestManager implements LifecycleListener {
// 仅贴出关键代码
...
public DrawableTypeRequest<String> load(String string) {
// 先调用fromString()再调用load()
// load()作用:传入图片URL地址
// fromString()作用 ->>分析1
return (DrawableTypeRequest<String>) fromString().load(string);
}
分析1:fromString()
public DrawableTypeRequest<String> fromString() {
// loadGeneric()的作用 ->>分析2
return loadGeneric(String.class);
}
分析2:loadGeneric()
private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) {
/* 创建第1个ModelLoader对象;作用:加载图片
Glide会根据load()方法传入不同类型参数,得到不同的ModelLoader对象
此处传入参数是String.class,因此得到的是StreamStringLoader对象(实现了ModelLoader接口)*/
ModelLoader<T, InputStream> streamModelLoader = Glide.buildStreamModelLoader(modelClass, context);
/* 创建第2个ModelLoader对象,作用同上:加载图片
此处得到的是FileDescriptorModelLoader对象*/
ModelLoader<T, ParcelFileDescriptor> fileDescriptorModelLoader = Glide.buildFileDescriptorModelLoader(modelClass, context);
/*创建DrawableTypeRequest对象 & 传入刚才创建的ModelLoader对象 和 其他初始化配置的参数*/
return optionsApplier.apply(
new DrawableTypeRequest<T> (modelClass, streamModelLoader, fileDescriptorModelLoader, context,
glide, requestTracker, lifecycle, optionsApplier)); //分析3
}
分析3 : DrawableTypeRequest.java
// 关注1:构造方法
public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<ModelType> implements DownloadOptions {
//通过构造函数将前面创建的对象依次初始化封装到DrawableTypeRequest
DrawableTypeRequest(Class<ModelType> modelClass, ModelLoader<ModelType, InputStream> streamModelLoader,
ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader, Context context, Glide glide,
RequestTracker requestTracker, Lifecycle lifecycle, RequestManager.OptionsApplier optionsApplier) {
super(context, modelClass,
//前面创建的两个modelLoader传入了buildProvider(),分析4
buildProvider(glide, streamModelLoader, fileDescriptorModelLoader, GifBitmapWrapper.class,
GlideDrawable.class, null),
glide, requestTracker, lifecycle);
//DrawableTypeRequest的方法之一:强制加载静态图片
public BitmapTypeRequest<ModelType> asBitmap() {
return optionsApplier.apply(new BitmapTypeRequest<ModelType>(this, streamModelLoader,
fileDescriptorModelLoader, optionsApplier));
// 创建BitmapTypeRequest对象
}
// asGif() 作用:强制加载 动态图片
public GifTypeRequest<ModelType> asGif() {
return optionsApplier.apply(new GifTypeRequest<ModelType>(this, streamModelLoader, optionsApplier));
// 创建GifTypeRequest对象
// 注:若没指定,则默认使用DrawableTypeRequest
}
}
分析4: buildProvider()
private static <A, Z, R> FixedLoadProvider<A, ImageVideoWrapper, Z, R> buildProvider(Glide glide,
ModelLoader<A, InputStream> streamModelLoader,
ModelLoader<A, ParcelFileDescriptor> fileDescriptorModelLoader, Class<Z> resourceClass,
Class<R> transcodedClass,
ResourceTranscoder<Z, R> transcoder) {
if (transcoder == null) {
// 创建GifBitmapWrapperDrawableTranscoder对象(实现了ResourceTranscoder接口)
// 作用:对图片进行转码
transcoder = glide.buildTranscoder(resourceClass, transcodedClass);
}
// 创建ImageVideoGifDrawableLoadProvider对象(实现了DataLoadProvider接口)
// 作用:对图片进行编解码
DataLoadProvider<ImageVideoWrapper, Z> dataLoadProvider = glide.buildDataProvider(ImageVideoWrapper.class,
resourceClass);
// 创建ImageVideoModelLoader
// 并把上面创建的两个ModelLoader:streamModelLoader和fileDescriptorModelLoader封装到了ImageVideoModelLoader中
ImageVideoModelLoader<A> modelLoader = new ImageVideoModelLoader<A>(streamModelLoader,
fileDescriptorModelLoader);
// 创建FixedLoadProvider对象
// 把上面创建的GifBitmapWrapperDrawableTranscoder、ImageVideoModelLoader、ImageVideoGifDrawableLoadProvider都封装进去
// 注:FixedLoadProvider对象就是第3步into()中onSizeReady()的loadProvider对象
return new FixedLoadProvider<A, ImageVideoWrapper, Z, R>(modelLoader, transcoder, dataLoadProvider);
}
在RequestManager的load()中,通过fromString()最终返回了一个DrawableTypeRequest对象,随后调用DrawableTypeRequest的into()方法,回看分析1,但是翻看DrawableTypeRequest源码,并没有load()方法和into()方法,这两个方法其实在它的父类里,我们来看看它们的继承关系:
public class DrawableRequestBuilder<ModelType>
extends GenericRequestBuilder<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable>
implements BitmapOptions, DrawableOptions {
...
// 最终load()方法返回的其实就是一个DrawableRequestBuilder对象
@Override
public DrawableRequestBuilder<ModelType> load(ModelType model) {
super.load(model);
return this;
}
// 特别注意:DrawableRequestBuilder类中有很多使用Glide的API方法,此处不做过多描述
@Override
public Target<GlideDrawable> into(ImageView view) {
return super.into(view);
}
}
1.2.3 总结
load()中预先创建好对图片进行一系列操作(加载、编解码、转码)的对象,并全部封装到 DrawableTypeRequest对象中
在这里插入图片描述
1.3 into()
1.3.1 作用
前面我们通过RequestManager的load()方法将加载图片需要的参数都封装进了DrawableTypeRequest对象进而调用其into()方法,此时这个方法只要就负责构建Request(Glide源码解析1 – Request的创建)和网络请求了
1.3.2 逻辑图
1.3.3 具体代码
前面已经说过,into()方法其实调用的是DrawableTypeRequest的父类DrawableRequestBuilder的load()方法,我们来看一下这个方法:
**DrawableRequestBuilder.java**
public class DrawableRequestBuilder<ModelType>
extends GenericRequestBuilder<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable>
implements BitmapOptions, DrawableOptions {
// 调用DrawableRequestBuilder的父类GenericRequestBuilder的into() ->>分析1
@Override
public Target<GlideDrawable> into(ImageView view) {
return super.into(view);
}
}
分析1:GenericRequestBuilder.java
public class GenericRequestBuilder<ModelType> {
...
public Target<TranscodeType> into(ImageView view) {
// 判断是否在主线程(跟新UI只能在主线程)
// 此处逻辑先不讲解,后面会详细说明,直接跳到方法的最后一行
Util.assertMainThread();
if (view == null) {
throw new IllegalArgumentException("You must pass in a non null View");
}
if (!isTransformationSet && view.getScaleType() != null) {
switch (view.getScaleType()) {
case CENTER_CROP:
applyCenterCrop();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
applyFitCenter();
break;
//$CASES-OMITTED$
default:
// Do nothing.
}
}
// 创建Target对象:用于最终展示图片 ->>分析2
// 从分析3回来
return into(glide.buildImageViewTarget(view, transcodeClass));
}
}
分析2:buildImageViewTarget.java
<R> Target<R> buildImageViewTarget(ImageView imageView, Class<R> transcodedClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodedClass);
// ->>分析3
}
分析3:ImageViewTargetFactory.java
public class ImageViewTargetFactory {
public <Z> Target<Z> buildTarget(ImageView view, Class<Z> clazz) {
// 根据传入的class参数构建不同的Target对象,分为三种情况:
// 情况1:若加载图片时调用了asBitmap(),那么构建的是BitmapImageViewTarget对象
// 情况2:否则构建的是GlideDrawableImageViewTarget对象
// 情况3:DrawableImageViewTarget对象基本用不到,此处忽略
// 具体请看以下代码
if (GlideDrawable.class.isAssignableFrom(clazz)) {
return (Target<Z>) new GlideDrawableImageViewTarget(view);
} else if (Bitmap.class.equals(clazz)) {
return (Target<Z>) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (Target<Z>) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException("Unhandled class: " + clazz
+ ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
}
这里主要将装载图片的VIew(ImageView)进行封装,大部分会封装成GlideDrawableImageViewTarget对象,最终作为参数传入GenericRequestBuilder的into()方法里(分析1)
**GenericRequestBuilder,java**
public <Y extends Target<TranscodeType>> Y into(Y target) {
// 关注1:构建Request对象:发出加载图片请求
Request request = buildRequest(target); 分析1
// 将请求设置到target
target.setRequest(request);
// 将target加入到lifecycle
lifecycle.addListener(target);
// 关注2:执行网络请求Request
requestTracker.runRequest(request); 分析2
return target;
}
分析1:**构建Request对象:**
private Request buildRequest(Target<TranscodeType> target) {
if (priority == null) {
priority = Priority.NORMAL;
}
return buildRequestRecursive(target, null); 分析2
}
private Request buildRequestRecursive(Target<TranscodeType> target, ThumbnailRequestCoordinator parentCoordinator) {
// 90%的代码用于处理缩略图,此处仅关注主流程,即如何构建Request对象
// 仅贴出关键代码(如何构建Request对象)
...
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest = obtainRequest(target, sizeMultiplier, priority, coordinator);
// 往下调用
}
private Request obtainRequest(Target<TranscodeType> target, float sizeMultiplier, Priority priority,
RequestCoordinator requestCoordinator) {
// 调用了GenericRequest的obtain()
// 作用:将在load()中调用的所有API参数都组装到Request对象当中
return GenericRequest.obtain(
loadProvider,
model,
signature,
context,
priority,
target,
sizeMultiplier,
placeholderDrawable,
placeholderId,
errorPlaceholder,
errorId,
fallbackDrawable,
fallbackResource,
requestListener,
requestCoordinator,
glide.getEngine(),
transformation,
transcodeClass,
isCacheable,
animationFactory,
overrideWidth,
overrideHeight,
diskCacheStrategy);
}
public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallback,
ResourceCallback {
// 仅贴出关键代码
...
public static <A, T, Z, R> GenericRequest<A, T, Z, R> obtain(
LoadProvider<A, T, Z, R> loadProvider,
A model,
Key signature,
Context context,
Priority priority,
Target<R> target,
float sizeMultiplier,
Drawable placeholderDrawable,
int placeholderResourceId,
Drawable errorDrawable,
int errorResourceId,
Drawable fallbackDrawable,
int fallbackResourceId,
RequestListener<? super A, R> requestListener,
RequestCoordinator requestCoordinator,
Engine engine,
Transformation<Z> transformation,
Class<R> transcodeClass,
boolean isMemoryCacheable,
GlideAnimationFactory<R> animationFactory,
int overrideWidth,
int overrideHeight,
DiskCacheStrategy diskCacheStrategy) {
@SuppressWarnings("unchecked")
GenericRequest<A, T, Z, R> request = (GenericRequest<A, T, Z, R>) REQUEST_POOL.poll();
if (request == null) {
request = new GenericRequest<A, T, Z, R>();
// 创建GenericRequest对象
}
// init()作用:将传入的Load()中的API参数赋值到GenericRequest的成员变量
request.init(loadProvider,
model,
signature,
context,
priority,
target,
sizeMultiplier,
placeholderDrawable,
placeholderResourceId,
errorDrawable,
errorResourceId,
fallbackDrawable,
fallbackResourceId,
requestListener,
requestCoordinator,
engine,
transformation,
transcodeClass,
isMemoryCacheable,
animationFactory,
overrideWidth,
overrideHeight,
diskCacheStrategy);
return request;
// 返回GenericRequest对象
}
...
}
到这里Request对象创建完毕
执行网络请求:requestTracker.runRequest(request);(分析2)
**requestTracker.java**
public void runRequest(Request request) {
// 此时的Request是GenericRequest对象
requests.add(request);
// 将每个提交的请求加入到一个set中:管理请求
// 判断Glide当前是否处于暂停状态
if (!isPaused) {
// 若不处于暂停状态,则调用GenericRequest的begin()来执行Request
request.begin(); //关注1
} else {
// 若处于暂停,则先将Request添加到待执行队列里面,等暂停状态解除后再执行
pendingRequests.add(request);
}
}
关注1 : GenericRequest.begin()
public void begin() {
startTime = LogTime.getLogTime();
//model可以看做是URL
if (model == null) {
onException(null); //分析1
return;
}
status = Status.WAITING_FOR_SIZE;
// 图片加载情况分两种:
// 1. Glide可以通过override()来制定宽高
// 2. 无使用
// 情况1:使用了override() API为图片指定了一个固定的宽高
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
onSizeReady(overrideWidth, overrideHeight); //分析2
} else {
target.getSize(this);
}
//情况2: target.onLoadStarted()
if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
// target.onLoadStarted()的内部会根据ImageView的layout_width和layout_height值做一系列的计算,来算出图片显示的宽高
// 计算后,也会调用onSizeReady()方法进行加载
target.onLoadStarted(getPlaceholderDrawable());
}
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}
分析1:若model=null,也就是URL,就会调用onException(),内部调用了setErrorPlaceholder()
private void setErrorPlaceholder(Exception e) {
Drawable error = model == null ? getFallbackDrawable() : null;
// 若有error的占位图,则采用先获取error的占位图
if (error == null) {
error = getErrorDrawable();
}
// 若没有error的占位图,则再去获取一个loading占位图
if (error == null) {
error = getPlaceholderDrawable();
}
target.onLoadFailed(e, error);
// 将占位图(error / loading)传入到onLoadFailed()中
}
**ImageViewTarget.java**
public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z> implements GlideAnimation.ViewAdapter {
...
@Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
view.setImageDrawable(errorDrawable);
// 将该error占位图显示到ImageView
}
@Override
public void onLoadStarted(Drawable placeholder) {
view.setImageDrawable(placeholder);
// 在图片请求开始前,会先使用Loading占位图代替最终的图片显示
// 在begin()时调用(回看分析7)
}
**看到这里就明白了我们常用到的占位图和error图在哪里被设置了吧!!**
分析2:onSizeReady()
public void onSizeReady(int width, int height) {
// loadProvider 对象 即 第2步load()中的FixedLoadProvider对象
// 里面封装了GifBitmapWrapperDrawableTranscoder、ImageVideoModelLoader、ImageVideoGifDrawableLoadProvider对象)
// ->>请回看第2步load()中的DrawableTypeRequest类
// 从loadProvider 对象中获取ImageVideoModelLoader对象
ModelLoader<A, T> modelLoader = loadProvider.getModelLoader();
// 从loadProvider 对象中获取GifBitmapWrapperDrawableTranscoder对象
ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder();
// 创建ImageVideoFetcher对象(传入HttpUrlFetcher对象)
final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height);
// ->>分析3
// 将上述获得的ImageVideoFetcher、GifBitmapWrapperDrawableTranscoder等一起传入到了Engine的load()方法中 ->>分析4
loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
priority, isMemoryCacheable, diskCacheStrategy, this);
}
...
}
分析3:ImageVideoModelLoader.getResourceFetcher()
public class ImageVideoModelLoader<A> implements ModelLoader<A, ImageVideoWrapper> {
@Override
public DataFetcher<ImageVideoWrapper> getResourceFetcher(A model, int width, int height) {
DataFetcher<ParcelFileDescriptor> fileDescriptorFetcher = null;
if (fileDescriptorLoader != null) {
// fileDescriptorLoader是在第2步load()中创建的FileDescriptorModelLoader:用于加载图片
// 调用FileDescriptorModelLoader的getResourceFetcher()会得到一个HttpUrlFetcher对象
fileDescriptorFetcher = fileDescriptorLoader.getResourceFetcher(model, width, height);
}
DataFetcher<InputStream> streamFetcher = null;
if (streamLoader != null) {
// streamLoader是在第2步load()中创建的StreamStringLoader:用于加载图片
// 调用streamLoader的getResourceFetcher()会得到一个HttpUrlFetcher对象
streamFetcher = streamLoader.getResourceFetcher(model, width, height);
}
if (streamFetcher != null || fileDescriptorFetcher != null) {
// 创建ImageVideoFetcher对象,并把上述获得的2个HttpUrlFetcher对象传进去
// 即调用ImageVideoModelLoader的getResourceFetcher()得到的是ImageVideoFetcher
return new ImageVideoFetcher(streamFetcher, fileDescriptorFetcher);
} else {
return null;
}
}
}
分析4:Engine.load()
public class Engine implements EngineJobListener,
MemoryCache.ResourceRemovedListener,
EngineResource.ResourceListener {
...
EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);
...这里省略了代码,主要是Glide的内存缓存,具体可以去看Glide源码解析3--内存缓存
// 创建EngineJob对象
// 作用:开启线程(作异步加载图片)
DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,
transcoder, diskCacheProvider, diskCacheStrategy, priority);
// 创建DecodeJob对象
// 作用:对图片解码(较复杂,下面会详细说明)
EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);
// 创建EngineRunnable对象
jobs.put(key, engineJob);
engineJob.addCallback(cb);
// 执行EngineRunnable对象
// 即在子线程中执行EngineRunnable的run()方法 ->>分析5
engineJob.start(runnable);
return new LoadStatus(cb, engineJob);
}
...
}
分析5:EngineRunnable.java
@Override
public void run() {
try {
// 调用decode() 并 返回了一个Resource对象 ->>分析6
resource = decode();
} catch (Exception e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Exception decoding", e);
}
...
}
private Resource<?> decode() throws Exception {
// 分两种情况:从缓存当中读(解码)图片 & 不从缓存中读(解码)图片
if (isDecodingFromCache()) {
// 若从缓存中decode图片:执行decodeFromCache()
// 本文先不讨论缓存情况,具体可以看Glide源码解析3 -- 内存缓存
return decodeFromCache();
} else {
// 不从缓存中读(解码)图片:执行decodeFromSource() ->>分析 7
return decodeFromSource();
}
}
分析7:decodeFromSource()
private Resource<?> decodeFromSource() throws Exception {
return decodeJob.decodeFromSource();
// 调用了DecodeJob的decodeFromSource()方法 ->>分析8
}
分析8:DecodeJob.decodeFromSource()
class DecodeJob<A, T, Z> {
...
public Resource<Z> decodeFromSource() throws Exception {
Resource<T> decoded = decodeSource();
// 获得Resource对象 ->>分析9
return transformEncodeAndTranscode(decoded);
// 调用transformEncodeAndTranscode()方法来处理该Resource对象。
}
分析9:decodeSource()
private Resource<T> decodeSource() throws Exception {
...
try {
final A data = fetcher.loadData(priority);
// 该fetcher是在分析2:onSizeReady()中得到的ImageVideoFetcher对象
// 即调用ImageVideoFetcher的loadData() - >>分析10
// 从分析12回来时看这里:
decoded = decodeFromSourceData(data);
// 将分析12创建的ImageVideoWrapper对象传入到decodeFromSourceData(),解码该对象 -->分析13
}
...
}
分析10: fetcher.loadData()
@Override
public ImageVideoWrapper loadData(Priority priority) throws Exception {
InputStream is = null;
if (streamFetcher != null) {
try {
// 该streamFetcher是创建ImageVideoFetcher对象时传入的HttpUrlFetcher
// 因此这里调用的是HttpUrlFetcher的loadData() ->>分析12
is = streamFetcher.loadData(priority);
} catch (Exception e) {
return new ImageVideoWrapper(is, fileDescriptor);
}
分析12:HttpUrlFetcher.loadData()
// 此处是网络请求的代码
public class HttpUrlFetcher implements DataFetcher<InputStream> {
@Override
public InputStream loadData(Priority priority) throws Exception {
return loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/, glideUrl.getHeaders());
// 继续往下看
}
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl, Map<String, String> headers)
...
// 静态工厂模式创建HttpURLConnection对象
urlConnection = connectionFactory.build(url);
for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
}
//设置请求参数
//设置连接超时时间2500ms
urlConnection.setConnectTimeout(2500);
//设置读取超时时间2500ms
urlConnection.setReadTimeout(2500);
//不使用http缓存
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
// Connect explicitly to avoid errors in decoders if connection fails.
urlConnection.connect();
if (isCancelled) {
return null;
}
final int statusCode = urlConnection.getResponseCode();
if (statusCode / 100 == 2) {
//请求成功
return getStreamForSuccessfulRequest(urlConnection);
// 继续往下看
}
}
private InputStream getStreamForSuccessfulRequest(HttpURLConnection urlConnection)
throws IOException {
if (TextUtils.isEmpty(urlConnection.getContentEncoding())) {
int contentLength = urlConnection.getContentLength();
stream = ContentLengthInputStream.obtain(urlConnection.getInputStream(), contentLength);
} else {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Got non empty content encoding: " + urlConnection.getContentEncoding());
}
stream = urlConnection.getInputStream();
}
return stream;
// 最终返回InputStream对象(但还没开始读取数据),回到分析9
}
}
}
我们回到分析9,继续看decodeFromSourceData()方法:
分析13:decodeFromSourceData()
// 将分析12创建的ImageVideoWrapper对象传入到decodeFromSourceData(),解码该对象
private Resource<T> decodeFromSourceData(A data) throws IOException {
decoded = loadProvider.getSourceDecoder().decode(data, width, height);
// 调用loadProvider.getSourceDecoder()得到的是GifBitmapWrapperResourceDecoder对象
// 即调用GifBitmapWrapperResourceDecoder对象的decode()来对图片进行解码 ->>分析14
return decoded;
}
分析14: GifBitmapWrapperResourceDecoder.decode()
public class GifBitmapWrapperResourceDecoder implements ResourceDecoder<ImageVideoWrapper, GifBitmapWrapper> {
...
@Override
public Resource<GifBitmapWrapper> decode(ImageVideoWrapper source, int width, int height) throws IOException {
wrapper = decode(source, width, height, tempBytes);
// 传入参数,并调用了另外一个decode()进行重载 ->>分析15
}
分析15:decode()
private GifBitmapWrapper decode(ImageVideoWrapper source, int width, int height, byte[] bytes) throws IOException {
final GifBitmapWrapper result;
if (source.getStream() != null) {
result = decodeStream(source, width, height, bytes);
// 作用:从服务器返回的流当中读取数据- >>分析16
} else {
result = decodeBitmapWrapper(source, width, height);
}
return result;
}
分析16:decodeStream()
// 作用:从服务器返回的流当中读取数据
// 读取方式:
// 1. 从流中读取2个字节的数据:判断该图是GIF图还是普通的静图
// 2. 若是GIF图,就调用decodeGifWrapper() 解码
// 3. 若普通静图,就调用decodeBitmapWrapper() 解码
// 此处仅分析 对于静图解码
private GifBitmapWrapper decodeStream(ImageVideoWrapper source, int width, int height, byte[] bytes)
throws IOException {
// 步骤1:从流中读取两个2字节数据进行图片类型的判断
InputStream bis = streamFactory.build(source.getStream(), bytes);
bis.mark(MARK_LIMIT_BYTES);
ImageHeaderParser.ImageType type = parser.parse(bis);
bis.reset();
GifBitmapWrapper result = null;
// 步骤2:若是GIF图,就调用decodeGifWrapper() 解码
if (type == ImageHeaderParser.ImageType.GIF) {
result = decodeGifWrapper(bis, width, height);
}
// 步骤3:若是普通静图,就调用decodeBitmapWrapper()解码
if (result == null) {
ImageVideoWrapper forBitmapDecoder = new ImageVideoWrapper(bis, source.getFileDescriptor());
result = decodeBitmapWrapper(forBitmapDecoder, width, height);
}
return result;
}
就分析到这里,下面的代码太过于复杂,我们主要知道下面是对静图和动图的解码,解码后封装到GifBitmapWrapper(既能封装GIF,又能封装Bitmap)
我们回到分析5:EngineRunnable的run()
@Override
public void run() {
try {
resource = decode();
// 最终得到了Resource<GlideDrawable>对象
// 接下来的工作:将该图片显示出来
} catch (Exception e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Exception decoding", e);
}
exception = e;
}
if (isCancelled) {
if (resource != null) {
resource.recycle();
}
return;
}
if (resource == null) {
onLoadFailed(exception);
} else {
onLoadComplete(resource);
// 表示图片加载已经完成 ->>分析17
}
}
分析17:onLoadComplete()
这里就是在主线程显示图片了:
private void onLoadComplete(Resource resource) {
manager.onResourceReady(resource);
// 该manager即EngineJob对象
// 实际上调用的是EngineJob的onResourceReady() - >>分析18
}
分析18:onResourceReady()
class EngineJob implements EngineRunnable.EngineRunnableManager {
...
private static final Handler MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper(), new MainThreadCallback());
// 创建线程,并绑定主线程的Looper
private final List<ResourceCallback> cbs = new ArrayList<ResourceCallback>();
@Override
public void onResourceReady(final Resource<?> resource) {
this.resource = resource;
MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
// 使用Handler发出一条 MSG_COMPLETE 消息
// 那么在MainThreadCallback的handleMessage()方法中就会收到这条消息 ->>分析19
// 从此处开始,所有逻辑又回到主线程中进行了,即更新UI
}
分析19:
private static class MainThreadCallback implements Handler.Callback {
@Override
public boolean handleMessage(Message message) {
if (MSG_COMPLETE == message.what || MSG_EXCEPTION == message.what) {
EngineJob job = (EngineJob) message.obj;
if (MSG_COMPLETE == message.what) {
job.handleResultOnMainThread();
// 调用 EngineJob的handleResultOnMainThread() ->>分析20
} else {
job.handleExceptionOnMainThread();
}
return true;
}
return false;
}
}
...
}
分析20:handleResultOnMainThread()
private void handleResultOnMainThread() {
// 通过循环,调用了所有ResourceCallback的onResourceReady()
for (ResourceCallback cb : cbs) {
if (!isInIgnoredCallbacks(cb)) {
engineResource.acquire(); //在缓存篇里提及过,acquire主要是acquire+1,表明图片正在使用
// ResourceCallback 是在Engine的load()方法当中添加的->>分析21
cb.onResourceReady(engineResource); 分析22
}
}
engineResource.release();
}
分析21:Engine.load()
public class Engine implements EngineJobListener,
MemoryCache.ResourceRemovedListener,
EngineResource.ResourceListener {
...
public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder, Priority priority,
boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
engineJob.addCallback(cb);
// 调用addCallback()注册了一个ResourceCallback
// 上述参数cb是load()传入的的最后一个参数
// 而load()是在GenericRequest的onSizeReady()调用的
return new LoadStatus(cb, engineJob);
}
...
}
public void onSizeReady(int width, int height) {
...
loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
priority, isMemoryCacheable, diskCacheStrategy, this);
// load()最后一个参数是this
// 所以,ResourceCallback类型参数cb是this
// 而GenericRequest本身实现了ResourceCallback接口
// 因此,EngineJob的回调 = cb.onResourceReady(engineResource) = 最终回调GenericRequest的onResourceReady()
}
}
分析22:GenericRequest的onResourceReady()
// 重载1
public void onResourceReady(Resource<?> resource) {
Object received = resource.get();
// 获取封装的图片对象(GlideBitmapDrawable对象 或 GifDrawable对象
onResourceReady(resource, (R) received);
// 然后将该获得的图片对象传入到了onResourceReady()的重载方法中 ->>看重载2
}
// 重载2
private void onResourceReady(Resource<?> resource, R result) {
...
target.onResourceReady(result, animation);
// Target是在第3步into()的最后1行调用glide.buildImageViewTarget()方法来构建出的Target:GlideDrawableImageViewTarget对象
// ->>分析23
}
分析23:GlideDrawableImageViewTarget.onResourceReady()
public class GlideDrawableImageViewTarget extends ImageViewTarget<GlideDrawable> {
@Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {
if (!resource.isAnimated()) {
float viewRatio = view.getWidth() / (float) view.getHeight();
float drawableRatio = resource.getIntrinsicWidth() / (float) resource.getIntrinsicHeight();
if (Math.abs(viewRatio - 1f) <= SQUARE_RATIO_MARGIN
&& Math.abs(drawableRatio - 1f) <= SQUARE_RATIO_MARGIN) {
resource = new SquaringDrawable(resource, view.getWidth());
}
}
super.onResourceReady(resource, animation);
// 若是静态图片,就调用父类的.onResourceReady() 将GlideDrawable显示到ImageView上
// GlideDrawableImageViewTarget的父类是ImageViewTarget ->>分析24
this.resource = resource;
resource.setLoopCount(maxLoopCount);
resource.start();
// 如果是GIF图片,就调用resource.start()方法开始播放图片
}
@Override
protected void setResource(GlideDrawable resource) {
view.setImageDrawable(resource); 分析25
}
...
}
分析24: ImageViewTarget.onResourceReady()
public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z> implements GlideAnimation.ViewAdapter {
...
@Override
public void onResourceReady(Z resource, GlideAnimation<? super Z> glideAnimation) {
if (glideAnimation == null || !glideAnimation.animate(resource, this)) {
setResource(resource);
// 继续往下看
}
}
protected abstract void setResource(Z resource);
// setResource()是一个抽象方法
// 需要在子类具体实现:请回看上面分析25子类GlideDrawableImageViewTarget类重写的setResource():调用view.setImageDrawable(),而这个view就是ImageView
// 即setResource()的具体实现是调用ImageView的setImageDrawable() 并 传入图片,于是就实现了图片显示。
}
1.3.5 总结
一图总结Glide的基本功能 图片加载的全过程