Glide的常用方式:
Glide.with(this).load(url).into(iv);
通过这一几个链式调用的方法就完成了从网络上加载一个图片在本地显示的功能,下面分析一下,内部的具体实现逻辑:
with()方法
首先看看Glide.with()方法:
public class Glide {
...
public static RequestManager with(Activity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(activity);
}
...
}
这个方法返回了一个RequestManager类型的对象。后面的load方法就是调用的RequestManager类的
load方法,下面看看这个方法的具体实现:
public class RequestManager implements LifecycleListener {
...
public DrawableTypeRequest<String> load(String string) {
return (DrawableTypeRequest<String>) fromString() //关键代码1
.load(string); // 关键代码2
}
...
public DrawableTypeRequest<String> fromString() {
//关键代码3
return loadGeneric(String.class);
}
private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) {
//关键代码4
ModelLoader<T, InputStream> streamModelLoader = Glide.buildStreamModelLoader(modelClass, context);
//关键代码5
ModelLoader<T, ParcelFileDescriptor> fileDescriptorModelLoader =
Glide.buildFileDescriptorModelLoader(modelClass, context);
if (modelClass != null && streamModelLoader == null && fileDescriptorModelLoader == null) {
throw new IllegalArgumentException("Unknown type " + modelClass + ". You must provide a Model of a type for"
+ " which there is a registered ModelLoader, if you are using a custom model, you must first call"
+ " Glide#register with a ModelLoaderFactory for your custom model class");
}
return optionsApplier.apply(
//关键代码6,,注意,这里的modelClass是String.class
new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
glide, requestTracker, lifecycle, optionsApplier));
}
class OptionsApplier {
public <A, X extends GenericRequestBuilder<A, ?, ?, ?>> X apply(X builder) {
//关键代码7
if (options != null) {
options.apply(builder);
}
return builder;
}
}
...
}
load()方法
在RequestManager类的load方法中,做了如下几件事:
1.在关键代码1处,调用了fromString()方法,接着调用了关键代码3处的loadGeneric方法,在接着在关键代码4创建了ModelLoader类型的streamModelLoader对象,下面看看这个streamModelLoader具体是什么ModelLoader的哪个子类型的对象:
public class Glide {
...
public static <T> ModelLoader<T, InputStream> buildStreamModelLoader(Class<T> modelClass, Context context) {
return buildModelLoader(modelClass, InputStream.class, context);
}
...
public static <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass,
Context context) {
if (modelClass == null) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Unable to load null model, setting placeholder only");
}
return null;
}
//关键代码处
return Glide.get(context).getLoaderFactory().buildModelLoader(modelClass, resourceClass);
}
...
}
这个方法内部调用了buildModelLoader,在关键代码处,调用了Glide.get(context).getLoaderFactory()生成了GenericLoaderFactory类型的对象,然后调用了GenericLoaderFactory类的buildModelLoader方法:
public class GenericLoaderFactory {
...
@Deprecated
public synchronized <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass,
Context context) {
return buildModelLoader(modelClass, resourceClass);
}
public synchronized <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass) {
ModelLoader<T, Y> result = getCachedLoader(modelClass, resourceClass);
...
//关键代码1
final ModelLoaderFactory<T, Y> factory = getFactory(modelClass, resourceClass);
if (factory != null) {
//关键代码2
result = factory.build(context, this);
cacheModelLoader(modelClass, resourceClass, result);
}
...
return result;
}
...
private <T, Y> ModelLoaderFactory<T, Y> getFactory(Class<T> modelClass, Class<Y> resourceClass) {
Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> resourceToFactories = modelClassToResourceFactories.get(modelClass);
ModelLoaderFactory/*T, Y*/ result = null;
if (resourceToFactories != null) {
result = resourceToFactories.get(resourceClass);
}
if (result == null) {
for (Class<? super T> registeredModelClass : modelClassToResourceFactories.keySet()) {
if (registeredModelClass.isAssignableFrom(modelClass)) {
Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> currentResourceToFactories =
modelClassToResourceFactories.get(registeredModelClass);
if (currentResourceToFactories != null) {
result = currentResourceToFactories.get(resourceClass);
if (result != null) {
break;
}
}
}
}
}
return result;
}
...
}
下面先分析关键代码1处,调用了getFactory方法,传入的参数就是String.class和InputStream.class。
在上面的getFactory方法中,是根据String.class这个key从modelClassToResourceFactories这个hashMap获取到期对应的value的,这个获取的value是一个HashMap,在继续向下分析之前,需要搞清楚,这个modelClassToResourceFactories是在哪里存放key和value的,其实是在Glide类的初始化的时候存入的。下面看看和本例相关的部分的Glide初始化的部分代码:
public class Glide {
...
Glide(Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, Context context, DecodeFormat decodeFormat) {
...
//关键代码1处,这里register()方法传入的参数分别是Sring.class,InputStream.class和StreamStringLoader.Factory对象
register(String.class, InputStream.class, new StreamStringLoader.Factory());
register(Uri.class, ParcelFileDescriptor.class, new FileDescriptorUriLoader.Factory());
register(Uri.class, InputStream.class, new StreamUriLoader.Factory());
register(URL.class, InputStream.class, new StreamUrlLoader.Factory());
register(GlideUrl.class, InputStream.class, new HttpUrlGlideUrlLoader.Factory());
}
...
public <T, Y> void register(Class<T> modelClass, Class<Y> resourceClass, ModelLoaderFactory<T, Y> factory) {
ModelLoaderFactory<T, Y> removed = loaderFactory.register(modelClass, resourceClass, factory);
if (removed != null) {
removed.teardown();
}
}
...
}
在关键代码1处,通过register方法,将String.class作为key,StreamStringLoader.Factory()对象作为value,存入到GenericLoaderFactory类的modelClassToResourceFactories这个hashMap中。在回到GenericLoaderFactory类的buildModelLoader方法,可以知道这个方法中的getFactory获取的其实就是StreamStringLoader.Factory()对象,在继续看GenericLoaderFactory类的buildModelLoader方法的关键代码2处,通过factory.build方法来获取ModelLoader类型的对象,下面看看StreamStringLoader.Factory类的build方法的具体实现:
public class StreamStringLoader extends StringLoader<InputStream> implements StreamModelLoader<String> {
/**
* The default factory for {@link com.bumptech.glide.load.model.stream.StreamStringLoader}s.
*/
public static class Factory implements ModelLoaderFactory<String, InputStream> {
@Override
public ModelLoader<String, InputStream> build(Context context, GenericLoaderFactory factories) {
return new StreamStringLoader(factories.buildModelLoader(Uri.class, InputStream.class));
}
@Override
public void teardown() {
// Do nothing.
}
}
...
}
这个方法内部,返回的是一个StreamStringLoader类型的对象。到这里弄清楚了Glide.buildStreamModelLoader(modelClass, context);这行代码返回的是StreamStringLoader类型的对象。到这里在RequestManager类的load方法中关键代码1处的代码分析完毕。
2.在RequestManager类的load方法中,关键代码5处,创建了ModelLoader类型的fileDescriptorModelLoader对象。
3.在在RequestManager类的load方法中,关键代码6处调用OptionsApplier类型的对象的apply方法,这个方法内部创建了一个DrawableTypeRequest对象,下面看看DrawableTypeRequest的构造方法:
public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<ModelType> implements DownloadOptions {
...
DrawableTypeRequest(Class<ModelType> modelClass, ModelLoader<ModelType, InputStream> streamModelLoader,
ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader, Context context, Glide glide,
RequestTracker requestTracker, Lifecycle lifecycle, RequestManager.OptionsApplier optionsApplier) {
//关键代码1,这里的modelClass是String.class
super(context, modelClass,
//关键代码2
buildProvider(glide, streamModelLoader, fileDescriptorModelLoader, GifBitmapWrapper.class,
GlideDrawable.class, null),
glide, requestTracker, lifecycle);
this.streamModelLoader = streamModelLoader;
this.fileDescriptorModelLoader = fileDescriptorModelLoader;
this.optionsApplier = optionsApplier;
}
...
}
这个构造方法内部在关键代码1处调用了其父类DrawableRequestBuilder的构造方法:
public class DrawableRequestBuilder<ModelType>
extends GenericRequestBuilder<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable>
implements BitmapOptions, DrawableOptions {
DrawableRequestBuilder(Context context, Class<ModelType> modelClass,
LoadProvider<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable> loadProvider, Glide glide,
RequestTracker requestTracker, Lifecycle lifecycle) {
//关键代码,第二个参数是String.class,第四个参数是GlideDrawable.class
super(context, modelClass, loadProvider, GlideDrawable.class, glide, requestTracker, lifecycle);
// Default to animating.
crossFade();
}
...
}
在这个方法内部的关键代码处,调用了DrawableRequestBuilder的父类GenericRequestBuilder的构造方法,注意传入其父类的构造方法的第一个参数是String.classs,第四个参数是GlideDrawable.class。这里先记录下来,后面要用到这个参数。在回到DrawableTypeRequest的构造方法的关键代码2处,调用了
buildProvider(glide, streamModelLoader, fileDescriptorModelLoader, GifBitmapWrapper.class,
GlideDrawable.class, null)
下面看看这个方法的具体实现(注意,传入的第二个参数streamModelLoader就是前面分析过的StreamStringLoader类型的对象,第四个参数是GifBitmapWrapper.class,第五个参数是GlideDrawable.class):
public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<ModelType> implements DownloadOptions {
...
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 (streamModelLoader == null && fileDescriptorModelLoader == null) {
return null;
}
if (transcoder == null) {
transcoder = glide.buildTranscoder(resourceClass, transcodedClass);
}
//关键代码1,resourceClass就是GifBitmapWrapper.class
DataLoadProvider<ImageVideoWrapper, Z> dataLoadProvider = glide.buildDataProvider(ImageVideoWrapper.class,
resourceClass);
//关键代码2,treamModelLoader就是前面分析过的StreamStringLoader类型的对象
ImageVideoModelLoader<A> modelLoader = new ImageVideoModelLoader<A>(streamModelLoader,
fileDescriptorModelLoader);
//关键代码3,modelLoader就是ImageVideoModelLoader,dataLoadProvider就是ImageVideoGifDrawableLoadProvider
return new FixedLoadProvider<A, ImageVideoWrapper, Z, R>(modelLoader, transcoder, dataLoadProvider);
}
...
在这个方法中的关键代码1处,通过Glide类的buildDataProvider()方法,创建了一个DataLoadProvider类型的对象,下面看看这个方法的具体实现:
public class Glide {
...
Glide(Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, Context context, DecodeFormat decodeFormat) {
dataLoadProviderRegistry = new DataLoadProviderRegistry();
...
dataLoadProviderRegistry = new DataLoadProviderRegistry();
StreamBitmapDataLoadProvider streamBitmapLoadProvider =
new StreamBitmapDataLoadProvider(bitmapPool, decodeFormat);
dataLoadProviderRegistry.register(InputStream.class, Bitmap.class, streamBitmapLoadProvider);
FileDescriptorBitmapDataLoadProvider fileDescriptorLoadProvider =
new FileDescriptorBitmapDataLoadProvider(bitmapPool, decodeFormat);
dataLoadProviderRegistry.register(ParcelFileDescriptor.class, Bitmap.class, fileDescriptorLoadProvider);
ImageVideoDataLoadProvider imageVideoDataLoadProvider =
new ImageVideoDataLoadProvider(streamBitmapLoadProvider, fileDescriptorLoadProvider);
dataLoadProviderRegistry.register(ImageVideoWrapper.class, Bitmap.class, imageVideoDataLoadProvider);
GifDrawableLoadProvider gifDrawableLoadProvider =
new GifDrawableLoadProvider(context, bitmapPool);
dataLoadProviderRegistry.register(InputStream.class, GifDrawable.class, gifDrawableLoadProvider);
//关键代码2
dataLoadProviderRegistry.register(ImageVideoWrapper.class, GifBitmapWrapper.class,
new ImageVideoGifDrawableLoadProvider(imageVideoDataLoadProvider, gifDrawableLoadProvider, bitmapPool));
dataLoadProviderRegistry.register(InputStream.class, File.class, new StreamFileDataLoadProvider());
}
<T, Z> DataLoadProvider<T, Z> buildDataProvider(Class<T> dataClass, Class<Z> decodedClass) {
//关键代码1,dataClass就是ImageVideoWrapper.class,decodedClass就是GifBitmapWrapper.class
return dataLoadProviderRegistry.get(dataClass, decodedClass);
}
}
Glide类的buildDataProvider()方法内部是通过dataLoadProviderRegistry这个变量的get方法,get方法内部其实是通过一个hashMap,根据传入的参数来获取相应的DataLoadProvider,而这个hashMap是在Glide类初始化时,就已经存入了很多的key和value,在上面的代码中的关键代码2处,可以看到,dataLoadProviderRegistry对象调用了
register方法,register方法内部,通过hashMap来将ImageVideWrapper.class和GifBitmapWrapper.class两个变量通合成为一个key,ImageVideoGifDrawableLoadProvider作为value存储,这样存储起来。而dataLoadProviderRegistry.get()方法中获取DataLoadProvider对象是,传入的参数正好是ImageVideoWrapper.class和GifBitmapWrapper.class,所以dataLoadProviderRegistry.get()方法返回的就是ImageVideoGifDrawableLoadProvider类型的对象。分析到这里,弄清楚了DrawableTypeRequest构造函数的关键代码1处的,
public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<ModelType> implements DownloadOptions {
...
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) {
...
//关键代码1,resourceClass就是GifBitmapWrapper.class
DataLoadProvider<ImageVideoWrapper, Z> dataLoadProvider = glide.buildDataProvider(ImageVideoWrapper.class,
resourceClass);
...
}
...
dataLoadProvider 其实就是ImageVideoGifDrawableLoadProvider类型的对象。这个对象在后面会用到。
下面继续分析DrawableTypeRequest构造函数的关键代码2处的代码:
public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<ModelType> implements DownloadOptions {
...
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) {
...
//关键代码2,treamModelLoader就是前面分析过的StreamStringLoader类型的对象
ImageVideoModelLoader<A> modelLoader = new ImageVideoModelLoader<A>(streamModelLoader,
fileDescriptorModelLoader);
...
}
在关键代码2处,这里构建一个ImageVideoModelLoader类型的对象,要注意传入ImageVideoModelLoader的构造函数中的streamModelLoader是StreamStringLoader类型的对象,至于ImageVideoModelLoader的构造函数中的初始化操作,后面会分析到,并且会用到StreamStringLoader类型的对象,这里只是强调一下。
下面继续分析DrawableTypeRequest构造函数的关键代码3处的代码
...
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) {
...
//关键代码3
return new FixedLoadProvider<A, ImageVideoWrapper, Z, R>(modelLoader, transcoder, dataLoadProvider);
...
}
在关键代码3处创建了一个FixedLoadProvider对象,注意传入的参数modelLoader就是ImageVideoModelLoader类型的对象,dataLoadProvider进过前面的分析可以知道就是ImageVideoGifDrawableLoadProvider类型的对象。
下面继续分析RequestManager类的load方法的关键代码6处,OptionsApplier类是RequestManager类的一个内部类,调用apply方法后,在关键代码7处,由于未给options赋值,这里options是为null的,所以直接返回传入的参数,也就是DrawableTypeRequest类型的对象。在关键代码2处,调用了DrawableTypeRequest的load方法,下面看看这个方法的具体实现:
public class DrawableRequestBuilder<ModelType>
extends GenericRequestBuilder<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable>
implements BitmapOptions, DrawableOptions {
...
@Override
public DrawableRequestBuilder<ModelType> load(ModelType model) {
super.load(model);
return this;
}
...
}
这个方法内部调用了其父类的load方法,下面看看父类GenericRequestBuilder的load方法
public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> implements Cloneable {
...
public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> load(ModelType model) {
this.model = model;
isModelSet = true;
return this;
}
...
}
GenericRequestBuilder类的load方法也仅仅是将传入的图片地址进行了保存.。到这里,分析完了Glide,with(this).load(url)这部分的链式调用的代码逻辑。
into()方法
下面继续看Glide,with(this).load(url).into(iv)这个链式调用的into方法的具体实现,通过上面的分析可以知道Glide.with(this).load(url)返回的是一个DrawableTypeRequest类型的对象,所以链式调用into方法就是调用的DrawableTypeRequest类的into方法,调用的这个into方法是其父类GlideDrawableRequestBuilder的into方法,下面看看这个方法的具体实现:
#DrawableRequestBuilder.java
public class DrawableRequestBuilder<ModelType>
extends GenericRequestBuilder<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable>
implements BitmapOptions, DrawableOptions {
...
@Override
public Target<GlideDrawable> into(ImageView view) {
return super.into(view);
}
...
}
这个方法内部调用了其父类GenericRequestBuilder的into方法
public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> implements Cloneable {
...
public Target<TranscodeType> into(ImageView view) {
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.
}
}
//关键代码1
return into(glide.buildImageViewTarget(view, transcodeClass));
}
}
这个方法内部,调用了另外一个重载的into方法,并通过glide.buildImageViewTarget(view, transcodeClass)创建了一个ViewTarget类型的对象。下面继续分析glide.buildImageViewTarget(view, transcodeClass)创建了ViewTarget的具体哪种类型的子对象。
#Glide.java
public class Glide {
...
<R> Target<R> buildImageViewTarget(ImageView imageView, Class<R> transcodedClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodedClass);
}
...
}
public class ImageViewTargetFactory {
@SuppressWarnings("unchecked")
public <Z> Target<Z> buildTarget(ImageView view, Class<Z> clazz) {
//关键代码
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)");
}
}
}
从前面分析的DrawableTypeRequest的构造方法时,在其方法内部调用了其父类的构造方法,传入其父类的构造方法的第四个参数是GlideDrawable.class,就是
imageViewTargetFactory.buildTarget(imageView, transcodedClass);这个方法内部的第二个参数,即transcoderClass就是GlideDrawable.class。所以,glide.buildImageViewTarget(view, transcodeClass)返回的是一个GlideDrawableImageViewTarget类型的对象,这个对象会到后面分析时用到。下面接着继续分析
DrawableTypeRequest的父类GenericRequestBuilder的into方法内部调用的其重载方法:
public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> implements Cloneable {
...
public <Y extends Target<TranscodeType>> Y into(Y target) {
Util.assertMainThread();
if (target == null) {
throw new IllegalArgumentException("You must pass in a non null Target");
}
if (!isModelSet) {
throw new IllegalArgumentException("You must first set a model (try #load())");
}
Request previous = target.getRequest();
if (previous != null) {
previous.clear();
requestTracker.removeRequest(previous);
previous.recycle();
}
//关键代码1
Request request = buildRequest(target);
target.setRequest(request);
lifecycle.addListener(target);
//关键代码2
requestTracker.runRequest(request);
return target;
}
...
private Request buildRequest(Target<TranscodeType> target) {
if (priority == null) {
priority = Priority.NORMAL;
}
return buildRequestRecursive(target, null);
}
private Request buildRequestRecursive(Target<TranscodeType> target, ThumbnailRequestCoordinator parentCoordinator) {
if (thumbnailRequestBuilder != null) {
...
return coordinator;
} else if (thumbSizeMultiplier != null) {
...
return coordinator;
} else {
// Base case: no thumbnail.
//关键代码
return obtainRequest(target, sizeMultiplier, priority, parentCoordinator);
}
}
private Request obtainRequest(Target<TranscodeType> target, float sizeMultiplier, Priority priority,
RequestCoordinator requestCoordinator) {
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);
}
}
在关键代码1处调用了buildRequest方法,这个方法内部又调用了buildRequestRecursive()方法,buildRequestRecursive()方法内部,由于未使用缩略图,所以前面两个if判断都不成立,会调用obtainRequest方法,最后调用到了GenericRequest.obtain()方法。GenericRequest.obtain()方法内部会根据传入的参数对GenericRequest的成员变量进行初始化,这里特别要注意,给GenericRequest进行初始化时,传入的target其实就是前面分析过的GlideDrawableImageViewTarget类型的对象。后面会用到这个参数。这里在次强调一下,便于读者加深映像。GenericRequest.obtain()方法返回的是GenericRequest类型的对象。所以前面调用的buidlRequest()方法返回的是GenericRequest类型的对象。后面会立刻用到这个对象。在次回到GenericRequestBuilder类的into方法,在关键代码2处,调用了
public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> implements Cloneable {
...
public <Y extends Target<TranscodeType>> Y into(Y target) {
...
//关键代码2
requestTracker.runRequest(request);
return target;
}
这行代码调用了RequestTracker 类的runRequest方法
public class RequestTracker {
...
public void runRequest(Request request) {
requests.add(request);
if (!isPaused) {
//关键代码
request.begin();
} else {
pendingRequests.add(request);
}
}
...
}
这个方法内部调用了request.begin()方法,经过前面的分析可以知道,这个request就是GenericRequest类型的对象。这样代码就执行到了GenericRequest类的begin方法中了:
public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallback,ResourceCallback {
...
@Override
public void begin() {
startTime = LogTime.getLogTime();
if (model == null) {
//关键代码1
onException(null);
return;
}
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
//关键代码2
onSizeReady(overrideWidth, overrideHeight);
} else {
//关键代码3
target.getSize(this);
}
if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
//关键代码4
target.onLoadStarted(getPlaceholderDrawable());
}
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}
}
这个方法中,下面分别分析4个关键代码处的代码,
在关键代码1处,如果model为null:
public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallback,ResourceCallback {
@Override
public void onException(Exception e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "load failed", e);
}
status = Status.FAILED;
//TODO: what if this is a thumbnail request?
if (requestListener == null || !requestListener.onException(e, model, target, isFirstReadyResource())) {
setErrorPlaceholder(e);
}
}
...
private void setErrorPlaceholder(Exception e) {
if (!canNotifyStatusChanged()) {
return;
}
Drawable error = model == null ? getFallbackDrawable() : null;
if (error == null) {
error = getErrorDrawable();
}
if (error == null) {
error = getPlaceholderDrawable();
}
//关键代码
target.onLoadFailed(e, error);
}
...
}
这个方法内部会调用到 target.onLoadFailed(e, error);这里的target前面已经多次强调过是GlideDrawableImageViewTarget类型的对象。所以代码跳转到了GlideDrawableImageViewTarget类的onLoadFailed(e, error)方法,由于GlideDrawableImageViewTarget类没有这个方法,发现是其父类的方法
public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z> implements GlideAnimation.ViewAdapter {
...
@Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
view.setImageDrawable(errorDrawable);
}
...
}
从这个方法可以看出,如果请求失败,会调用传入的ImageView的setImageDrawable(errorDrawable)方法将错误图片显示出来。
下面继续分析GenericRequest类的begin方法中关键2处和关键3处的代码,通过分析,无论是走关键2还是关键3处的逻辑,都会调用到onSizeReady方法,下面看看这个方法的具体实现:
public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallback, ResourceCallback {
@Override
public void onSizeReady(int width, int height) {
...
//关键代码1,这里的loadProvider其实就是FixedLoadProvider对象
ModelLoader<A, T> modelLoader = loadProvider.getModelLoader();
//关键代码2
final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height);
if (dataFetcher == null) {
onException(new Exception("Failed to load model: \'" + model + "\'"));
return;
}
ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
}
loadedFromMemoryCache = true;
//关键代码3
loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
priority, isMemoryCacheable, diskCacheStrategy, this);
loadedFromMemoryCache = resource != null;
...
}
}
在这个方法的关键代码1处,调用了loadProvider.getModelLoader()方法,这里的loadProvider是在GenericRequest的初始化赋值的,在前面的分析知道,这里的 loadProvider其实就是FixedLoadProvider类型的对象。这样loadProvider.getModelLoader()执行的就是FixedLoadProvider类的getModelLoader()方法,下面看看这个方法:
public class FixedLoadProvider<A, T, Z, R> implements LoadProvider<A, T, Z, R> {
...
@Override
public ModelLoader<A, T> getModelLoader() {
return modelLoader;
}
...
}
这个方法内部就是返回了一个FixedLoadProvider类的成员变量modelLoader,在前面分析FixedLoadProvider类初始化时,就已经强调过,传入FixedLoadProvider类的构造函数的这个modelLoader是是ImageVideoModelLoader类型的对象,所以loadProvider.getModelLoader()方法返回的就是ImageVideoModelLoader类型的对象。在继续分析GenericRequest类的onSizeReady()方法的关键代码2处的代码:
public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallback, ResourceCallback {
@Override
public void onSizeReady(int width, int height) {
...
//关键代码1,这里的loadProvider其实就是FixedLoadProvider对象
ModelLoader<A, T> modelLoader = loadProvider.getModelLoader();
//关键代码2
final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height);
...
}
}
前面已经分析过关键代码1处的modelLoader 其实就是ImageVideoModelLoader类型的对象,在关键代码2处,就是调用的ImageVideoModelLoader类的getResourceFetcher()方法。下面看看这个方法的具体实现:
public class ImageVideoModelLoader<A> implements ModelLoader<A, ImageVideoWrapper> {
@Override
public DataFetcher<ImageVideoWrapper> getResourceFetcher(A model, int width, int height) {
DataFetcher<InputStream> streamFetcher = null;
if (streamLoader != null) {
//关键代码1
streamFetcher = streamLoader.getResourceFetcher(model, width, height);
}
DataFetcher<ParcelFileDescriptor> fileDescriptorFetcher = null;
if (fileDescriptorLoader != null) {
fileDescriptorFetcher = fileDescriptorLoader.getResourceFetcher(model, width, height);
}
if (streamFetcher != null || fileDescriptorFetcher != null) {
//关键代码2
return new ImageVideoFetcher(streamFetcher, fileDescriptorFetcher);
} else {
return null;
}
}
}
在这个方法的关键代码2处,返回了一个ImageVideoFetcher类型的对象。但是在创建ImageVideoFetcher类型的对象时,传入的构造函数的第一个参数streamFetcher是在关键代码1处生成的,这个streamFetcher很重要,后面会用到,这里先分析下,这个streamFetcher究竟是个什么东东?这个streamFetcher是通过
关键代码1处的streamLoader.getResourceFetcher(model, width, height)方法获取的,通过前面的分析可以知道这个streamLoader其实就是StreamStringLoader类型的对象,所以,代码跳转到了StreamStringLoader类的getResourceFetcher()方法,通过查看源码发现,getResourceFetcher()方法是StreamStringLoader类的父类StringLoader的方法:
public class StringLoader<T> implements ModelLoader<String, T> {
...
@Override
public DataFetcher<T> getResourceFetcher(String model, int width, int height) {
Uri uri;
if (TextUtils.isEmpty(model)) {
return null;
} else if (model.startsWith("/")) {
uri = toFileUri(model);
} else {
uri = Uri.parse(model);
final String scheme = uri.getScheme();
if (scheme == null) {
uri = toFileUri(model);
}
}
// 关键代码
return uriLoader.getResourceFetcher(uri, width, height);
}
...
}
这个方法内部通过uriLoader的getResourceFetcher()方法来返回一个DataFetcher类型的对象。在继续往下分析前, 要弄清楚,这个uriLoader是从哪里来的,前面分析过,StreamStringLoader.Factory类的build方法的具体实现:
public class StreamStringLoader extends StringLoader<InputStream> implements StreamModelLoader<String> {
/**
* The default factory for {@link com.bumptech.glide.load.model.stream.StreamStringLoader}s.
*/
public static class Factory implements ModelLoaderFactory<String, InputStream> {
@Override
public ModelLoader<String, InputStream> build(Context context, GenericLoaderFactory factories) {
return new StreamStringLoader(factories.buildModelLoader(Uri.class, InputStream.class));
}
@Override
public void teardown() {
// Do nothing.
}
}
...
}
这个方法内部调用的StreamStringLoader的构造方法,并通过factories.buildModelLoader(Uri.class, InputStream.class)来给这个uriLoader赋值的,如果弄清楚了factories.buildModelLoader(Uri.class, InputStream.class)这行代码的逻辑,就能确定uriLoader的值了。下面来分析这行代码的逻辑,这行代码调用的是
GenericLoaderFactory 类的buildModelLoader方法,注意,传入的参数是Uri.class和InputStream.class.
public class GenericLoaderFactory {
...
/**
* Returns a {@link ModelLoader} for the given model and resource classes by either returning a cached
* {@link ModelLoader} or building a new a new {@link ModelLoader} using registered {@link ModelLoaderFactory}s.
* Returns null if no {@link ModelLoaderFactory} is registered for the given classes.
*
* @param modelClass The model class.
* @param resourceClass The resource class.
* @param <T> The type of the model.
* @param <Y> The type of the resource.
*/
public synchronized <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass) {
ModelLoader<T, Y> result = getCachedLoader(modelClass, resourceClass);
if (result != null) {
if (NULL_MODEL_LOADER.equals(result)) {
return null;
} else {
return result;
}
}
//关键代码1
final ModelLoaderFactory<T, Y> factory = getFactory(modelClass, resourceClass);
if (factory != null) {
// 关键代码2
result = factory.build(context, this);
cacheModelLoader(modelClass, resourceClass, result);
} else {
// We can't generate a model loader for the given arguments with the currently registered set of factories.
cacheNullLoader(modelClass, resourceClass);
}
return result;
}
...
private <T, Y> ModelLoaderFactory<T, Y> getFactory(Class<T> modelClass, Class<Y> resourceClass) {
Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> resourceToFactories = modelClassToResourceFactories.get(modelClass);
ModelLoaderFactory/*T, Y*/ result = null;
if (resourceToFactories != null) {
result = resourceToFactories.get(resourceClass);
}
if (result == null) {
for (Class<? super T> registeredModelClass : modelClassToResourceFactories.keySet()) {
if (registeredModelClass.isAssignableFrom(modelClass)) {
Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> currentResourceToFactories =
modelClassToResourceFactories.get(registeredModelClass);
if (currentResourceToFactories != null) {
result = currentResourceToFactories.get(resourceClass);
if (result != null) {
break;
}
}
}
}
}
return result;
}
...
}
在这个方法的关键代码1处,会调用getFactory方法,getFactory方法内部会通过传入的参数作为key从modelClassToResourceFactories这个hashMap,中取出相应的value。这里传入的key是Uri.class。在继续分析下去之前,在次看看Glide的初始化:
public class Glide {
...
Glide(Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, Context context, DecodeFormat decodeFormat) {
...
//关键代码处,这里传入register方法的参数分别是Uri.class,InputStream.class和StreamStringLoader.Factory对象
register(Uri.class, InputStream.class, new StreamUriLoader.Factory());
...
}
...
}
从Glide的初始化调用了register方法,其实就是在将Uri.class作为key,StreamUriLoader.Factory这个对象作为value保存到GenericLoaderFactory的modelClassToResourceFactories这个hashMap中,所在上面分析的getFactory方法,传入的参数是Uri.class时,返回的是StreamUriLoader.Factory这个对象。下面继续分析GenericLoaderFactory 类的buildModelLoader()方法的关键代码2处
public class GenericLoaderFactory {
...
public synchronized <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass) {
ModelLoader<T, Y> result = getCachedLoader(modelClass, resourceClass);
...
//关键代码1
final ModelLoaderFactory<T, Y> factory = getFactory(modelClass, resourceClass);
if (factory != null) {
// 关键代码2
result = factory.build(context, this);
cacheModelLoader(modelClass, resourceClass, result);
}
...
return result;
}
经过前面的分析知道,关键代码1处获取的factory是StreamUriLoader.Factory类型的,关键代码2处就是调用了StreamUriLoader.Factory的build方法。
public class StreamUriLoader extends UriLoader<InputStream> implements StreamModelLoader<Uri> {
public static class Factory implements ModelLoaderFactory<Uri, InputStream> {
@Override
public ModelLoader<Uri, InputStream> build(Context context, GenericLoaderFactory factories) {
return new StreamUriLoader(context, factories.buildModelLoader(GlideUrl.class, InputStream.class));
}
@Override
public void teardown() {
// Do nothing.
}
}
...
}
这个方法内部返回的是一个StreamUriLoader类型的对象,到此,弄清楚了StreamStringLoader类的父类StringLoader的getResourceFetcher()方法中的uriLoader就是StreamUriLoader类型的对象。下面再次贴出
StringLoader的getResourceFetcher()方法,由于是重复贴出代码,为了减少文字篇幅,这里省略了更多的代码:
public class StringLoader<T> implements ModelLoader<String, T> {
...
@Override
public DataFetcher<T> getResourceFetcher(String model, int width, int height) {
...
// 关键代码
return uriLoader.getResourceFetcher(uri, width, height);
}
...
}
通过前面分析知道这个方法中uriLoader是StreamUriLoader类型的,所以代码就跳转到了StreamUriLoader类的getResourceFetcher()方法中,StreamUriLoader类中没有这个方法,是其父类UriLoader的方法
public abstract class UriLoader<T> implements ModelLoader<Uri, T> {
private final Context context;
private final ModelLoader<GlideUrl, T> urlLoader;
public UriLoader(Context context, ModelLoader<GlideUrl, T> urlLoader) {
this.context = context;
this.urlLoader = urlLoader;
}
@Override
public final DataFetcher<T> getResourceFetcher(Uri model, int width, int height) {
final String scheme = model.getScheme();
DataFetcher<T> result = null;
if (isLocalUri(scheme)) {
if (AssetUriParser.isAssetUri(model)) {
String path = AssetUriParser.toAssetPath(model);
result = getAssetPathFetcher(context, path);
} else {
result = getLocalUriFetcher(context, model);
}
} else if (urlLoader != null && ("http".equals(scheme) || "https".equals(scheme))) {
//关键代码处
result = urlLoader.getResourceFetcher(new GlideUrl(model.toString()), width, height);
}
return result;
}
...
在这个方法内部,可以看到通过model.getScheme()方法来获取scheme,平时开发时,从网络获取图片时,传入的url地址,一般都是http或者https开头的,所以这个方法内部代码的逻辑执行到关键代码处,这里又调用了urlLoader的getResourceFetcher方法,现在需要弄清楚,urlLoader是从哪里来的,这个urlLoader是通过StreamUriLoader 的构造函数传入并赋值的,经过前面的分析知道,StreamUriLoader的构造函数的调用是在
StreamUriLoader.Factory的build方法中。
public class StreamUriLoader extends UriLoader<InputStream> implements StreamModelLoader<Uri> {
public static class Factory implements ModelLoaderFactory<Uri, InputStream> {
@Override
public ModelLoader<Uri, InputStream> build(Context context, GenericLoaderFactory factories) {
return new StreamUriLoader(context, factories.buildModelLoader(GlideUrl.class, InputStream.class));
}
@Override
public void teardown() {
// Do nothing.
}
}
...
}
这个urlLoader的值就是通过factories.buildModelLoader(GlideUrl.class, InputStream.class)来赋值的,
factories.buildModelLoader(GlideUrl.class, InputStream.class)的分析过程,前面已经分析过了,这里就进行简单的分析,注意这里传入的是GlideUrl.class和InputStream.class,在分析前,在看看Glide的初始化,:
public class Glide {
...
Glide(Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, Context context, DecodeFormat decodeFormat) {
...
//关键代码处,这里register()方法传入的参数分别是GlideUrl.class,InputStream.class和new HttpUrlGlideUrlLoader.Factory对象
register(GlideUrl.class, InputStream.class, new HttpUrlGlideUrlLoader.Factory());
...
}
...
}
所以GenericLoaderFactory的buildModelLoader方法内部获取的factory就是HttpUrlGlideUrlLoader.Factory,factory调动的build方法就是执行的HttpUrlGlideUrlLoader.Factory的build方法
public class HttpUrlGlideUrlLoader implements ModelLoader<GlideUrl, InputStream> {
private final ModelCache<GlideUrl, GlideUrl> modelCache;
/**
* The default factory for {@link com.bumptech.glide.load.model.stream.HttpUrlGlideUrlLoader}s.
*/
public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
private final ModelCache<GlideUrl, GlideUrl> modelCache = new ModelCache<GlideUrl, GlideUrl>(500);
@Override
public ModelLoader<GlideUrl, InputStream> build(Context context, GenericLoaderFactory factories) {
return new HttpUrlGlideUrlLoader(modelCache);
}
@Override
public void teardown() {
// Do nothing.
}
}
...
从build方法中,可以知道,返回的是一个HttpUrlGlideUrlLoader类型的对象,到这里弄清楚了StreamUriLoader类的getResourceFetcher()方法中
public abstract class UriLoader<T> implements ModelLoader<Uri, T> {
private final Context context;
private final ModelLoader<GlideUrl, T> urlLoader;
...
@Override
public final DataFetcher<T> getResourceFetcher(Uri model, int width, int height) {
final String scheme = model.getScheme();
DataFetcher<T> result = null;
if (isLocalUri(scheme)) {
...
} else if (urlLoader != null && ("http".equals(scheme) || "https".equals(scheme))) {
//关键代码处
result = urlLoader.getResourceFetcher(new GlideUrl(model.toString()), width, height);
}
return result;
}
...
这个方法中的urlLoader的值就是HttpUrlGlideUrlLoader类型的对象。
urlLoader.getResourceFetcher(new GlideUrl(model.toString()), width, height)执行的就是HttpUrlGlideUrlLoader类的getResourceFetcher方法:
public class HttpUrlGlideUrlLoader implements ModelLoader<GlideUrl, InputStream> {
...
@Override
public DataFetcher<InputStream> getResourceFetcher(GlideUrl model, int width, int height) {
// GlideUrls memoize parsed URLs so caching them saves a few object instantiations and time spent parsing urls.
GlideUrl url = model;
if (modelCache != null) {
url = modelCache.get(model, 0, 0);
if (url == null) {
modelCache.put(model, 0, 0, model);
url = model;
}
}
return new HttpUrlFetcher(url);
}
}
这个方法内部返回了一个HttpUrlFetcher类型的对象。到这里才刚刚分析完GenericRequest类的onSizeReady方法的关键代码2处的dataFetcher 就是HttpUrlFetcher类型的对象。
public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallback, ResourceCallback {
@Override
public void onSizeReady(int width, int height) {
...
//关键代码1,这里的loadProvider其实就是FixedLoadProvider对象
ModelLoader<A, T> modelLoader = loadProvider.getModelLoader();
//关键代码2
final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height);
if (dataFetcher == null) {
onException(new Exception("Failed to load model: \'" + model + "\'"));
return;
}
ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
}
loadedFromMemoryCache = true;
//关键代码3
loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
priority, isMemoryCacheable, diskCacheStrategy, this);
loadedFromMemoryCache = resource != null;
...
}
}
下面继续分析GenericRequest类的onSizeReady方法的关键代码3处的逻辑,这里会调用Engine类的load方法,注意传入的dataFetcher参数是HttpUrlFetcher类型的对象,传入的loadProvider是FixedLoadProvider类型的对象。
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) {
Util.assertMainThread();
long startTime = LogTime.getLogTime();
final String id = fetcher.getId();
EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
transcoder, loadProvider.getSourceEncoder());
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
cb.onResourceReady(cached);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
EngineJob current = jobs.get(key);
if (current != null) {
current.addCallback(cb);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
//关键代码1
EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);
//关键代码2
DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,
transcoder, diskCacheProvider, diskCacheStrategy, priority);
//关键代码3
EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);
jobs.put(key, engineJob);
engineJob.addCallback(cb);
//关键代码4
engineJob.start(runnable);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new LoadStatus(cb, engineJob);
}
这个方法内部会在关键代码1处创建一个EngineJob类型的对象,在关键代码2处,创建一个DecodeJob类型的对象,注意传入的构造函数的第4个参数是HttpUrlFetcher类型的对象,传入的l第5个参数是FixedLoadProvider类型的对象 在关键代码3处,创建一个EngineRunnable类型的对象,在关键代码4处调用EngineJob类的start()方法,这样
EngineRunnable的润方法就会执行,下面看看EngineRunnable 的run方法的具体实现:
class EngineRunnable implements Runnable, Prioritized {
...
@Override
public void run() {
if (isCancelled) {
return;
}
Exception exception = null;
Resource<?> resource = null;
try {
//关键代码1
resource = decode();
} 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) {
//关键代码2
onLoadFailed(exception);
} else {
//关键代码3
onLoadComplete(resource);
}
}
...
private Resource<?> decode() throws Exception {
if (isDecodingFromCache()) {
return decodeFromCache();
} else {
return decodeFromSource();
}
}
...
private Resource<?> decodeFromSource() throws Exception {
return decodeJob.decodeFromSource();
}
...
}
在EngineRunnable的run方法的关键代码1处,会调用decode方法,在decode方法中,会如果已经缓存了,则走decodeFromCache()的逻辑,否则执行decodeFromSource()逻辑,下面以decodeFromSource()这个逻辑为例来继续下面的分析,decodeFromSource()逻辑这块的逻辑,读者可以自己去分析。
decodeFromSource()方法内部是调用了DecodeJob类的decodeFromSource()方法,下面看看这个方法
class DecodeJob<A, T, Z> {
...
public Resource<Z> decodeFromSource() throws Exception {
Resource<T> decoded = decodeSource();
return transformEncodeAndTranscode(decoded);
}
...
private Resource<T> decodeSource() throws Exception {
Resource<T> decoded = null;
try {
long startTime = LogTime.getLogTime();
//关键代码1
final A data = fetcher.loadData(priority);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Fetched data", startTime);
}
if (isCancelled) {
return null;
}
//关键代码2
decoded = decodeFromSourceData(data);
} finally {
fetcher.cleanup();
}
return decoded;
}
...
}
在这个方法的关键代码1处,调用了fetcher.loadData(priority),这里的fetcher就是前面花了很大的篇幅分析得出的HttpUrlFetcher类型的对象。这样代码跳转到了HttpUrlFetcher类的loadData方法中,注意方法的参数传入的是一个priority,也就是,可以调整线程的优先级的,这表明Glide是可以设置线程的优先级的。下面看看HttpUrlFetcher类的loadData方法
public class HttpUrlFetcher implements DataFetcher<InputStream> {
...
private static final int MAXIMUM_REDIRECTS = 5;
...
@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)
throws IOException {
//如果重定向的次数超过5次,则抛出异常
if (redirects >= MAXIMUM_REDIRECTS) {
throw new IOException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
} else {
// Comparing the URLs using .equals performs additional network I/O and is generally broken.
// See http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html.
try {
if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
throw new IOException("In re-direct loop");
}
} catch (URISyntaxException e) {
// Do nothing, this is best effort.
}
}
//创建urlConnection对象,并进行网络请求
urlConnection = connectionFactory.build(url);
for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
}
urlConnection.setConnectTimeout(2500);
urlConnection.setReadTimeout(2500);
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) {
//statusCode是200.表示成功
return getStreamForSuccessfulRequest(urlConnection);
} else if (statusCode / 100 == 3) {
String redirectUrlString = urlConnection.getHeaderField("Location");
if (TextUtils.isEmpty(redirectUrlString)) {
throw new IOException("Received empty or null redirect url");
}
URL redirectUrl = new URL(url, redirectUrlString);
return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
} else {
if (statusCode == -1) {
throw new IOException("Unable to retrieve response code from HttpUrlConnection.");
}
throw new IOException("Request failed " + statusCode + ": " + urlConnection.getResponseMessage());
}
}
...
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;
}
...
}
HttpUrlFetcher 类的loadData方法内部会调用到loadDataWithRedirects()方法,loadDataWithRedirects()内部会通过HttpURLConnection进行网络请求,并调用getStreamForSuccessfulRequest()方法并获取返回的InputStream。
到这里才分析到Glide加载图片的网络请求。
回到DecodeJob类的decodeFromSource()方法,下面看看这个方法
class DecodeJob<A, T, Z> {
...
private Resource<T> decodeSource() throws Exception {
Resource<T> decoded = null;
try {
long startTime = LogTime.getLogTime();
//关键代码1
final A data = fetcher.loadData(priority);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Fetched data", startTime);
}
if (isCancelled) {
return null;
}
//关键代码2
decoded = decodeFromSourceData(data);
} finally {
fetcher.cleanup();
}
return decoded;
}
...
}
关键代码1处,完成了网络请求,并返回了InputStream,在关键代码2处,处理流对象,将流对象解码Bitmap或者Drawable类型的对象,这样ImageView才能直接使用。关键代码2处会调用decodeFromSourceData方法,
class DecodeJob<A, T, Z> {
...
private Resource<T> decodeFromSourceData(A data) throws IOException {
final Resource<T> decoded;
if (diskCacheStrategy.cacheSource()) {
//关键代码,调用
decoded = cacheAndDecodeSourceData(data);
} else {
long startTime = LogTime.getLogTime();
decoded = loadProvider.getSourceDecoder().decode(data, width, height);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Decoded from source", startTime);
}
}
return decoded;
}
...
}
由于Glide.with(this).load(url).into(iv);这个链式调用默认的DiskCacheStrategy.RESULT,这就导致
if (diskCacheStrategy.cacheSource()) 这个判断条件不成立,会执行else分支的逻辑,下面以if分支的逻辑为例来分析,代码执行到关键代码处cacheAndDecodeSourceData()方法,
class DecodeJob<A, T, Z> {
private Resource<T> cacheAndDecodeSourceData(A data) throws IOException {
long startTime = LogTime.getLogTime();
//将InputStream转换成 SourceWriter类型的对象
SourceWriter<A> writer = new SourceWriter<A>(loadProvider.getSourceEncoder(), data);
//将SourceWriter类型的对象写入磁盘缓存,也就是缓存图片到磁盘
diskCacheProvider.getDiskCache().put(resultKey.getOriginalKey(), writer);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Wrote source to cache", startTime);
}
startTime = LogTime.getLogTime();
//关键代码
Resource<T> result = loadFromCache(resultKey.getOriginalKey());
if (Log.isLoggable(TAG, Log.VERBOSE) && result != null) {
logWithTimeAndKey("Decoded source from cache", startTime);
}
return result;
}
private Resource<T> loadFromCache(Key key) throws IOException {
File cacheFile = diskCacheProvider.getDiskCache().get(key);
if (cacheFile == null) {
return null;
}
Resource<T> result = null;
try {
//关键代码
result = loadProvider.getCacheDecoder().decode(cacheFile, width, height);
} finally {
if (result == null) {
diskCacheProvider.getDiskCache().delete(key);
}
}
return result;
}
...
}
在DecodeJob类的cacheAndDecodeSourceData方法只,会将网络请求的流数据转换成 SourceWriter类型的对象的对象,并缓存到磁盘,接着调用loadFromCache()方法从缓存中获取数据,这个方法内部,又调用了loadProvider.getCacheDecoder().decode(cacheFile, width, height)来返回结果。
这个loadProvider是什么类型的呢?前面在创建DecodeJob对象时,就提过传入的第4个参数是第HttpUrlFetcher类型的对象,传入的l第5个参数是FixedLoadProvider类型的对象 ,所以,这里的loadProvider其实就是FixedLoadProvider类型的对象。
所以代码又跳转到了FixedLoadProvider类的getCacheDecoder()方法:
@Override
public ResourceDecoder<File, Z> getCacheDecoder() {
return dataLoadProvider.getCacheDecoder();
}
这个方法内部又是通过dataLoadProvider.getCahcedDecoder()来返回的。前面继续分析DrawableTypeRequest构造函数的关键代码3处的代码
...
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) {
...
//关键代码3
return new FixedLoadProvider<A, ImageVideoWrapper, Z, R>(modelLoader, transcoder, dataLoadProvider);
...
}
在关键代码3处创建了一个FixedLoadProvider对象,注意传入的参数modelLoader就是ImageVideoModelLoader类型的对象,dataLoadProvider进过前面的分析可以知道就是ImageVideoGifDrawableLoadProvider类型的对象。可以知道FixedLoadProvider类的getCacheDecoder()方法内部的dataLoadProvider其实就是ImageVideoGifDrawableLoadProvider类型的对象。这样代码就跳转到了ImageVideoGifDrawableLoadProvider类的getCacheDecoder()方法
public class ImageVideoGifDrawableLoadProvider implements DataLoadProvider<ImageVideoWrapper, GifBitmapWrapper> {
...
public ImageVideoGifDrawableLoadProvider(DataLoadProvider<ImageVideoWrapper, Bitmap> bitmapProvider,
DataLoadProvider<InputStream, GifDrawable> gifProvider, BitmapPool bitmapPool) {
//关键代码3
final GifBitmapWrapperResourceDecoder decoder = new GifBitmapWrapperResourceDecoder(
//关键代码4
bitmapProvider.getSourceDecoder(),
gifProvider.getSourceDecoder(),
bitmapPool
);
//关键代码2
cacheDecoder = new FileToStreamDecoder<GifBitmapWrapper>(new GifBitmapWrapperStreamResourceDecoder(decoder));
sourceDecoder = decoder;
encoder = new GifBitmapWrapperResourceEncoder(bitmapProvider.getEncoder(), gifProvider.getEncoder());
//TODO: what about the gif provider?
sourceEncoder = bitmapProvider.getSourceEncoder();
}
@Override
public ResourceDecoder<File, GifBitmapWrapper> getCacheDecoder() {
//关键代码1
return cacheDecoder;
}
...
}
这个方法的关键代码1处内部返回的cacheDecoder是在关键代码2处赋值的,返回了一个FileToStreamDecoder类型的对象。这个FileToStreamDecoder类型的对象内部又封装了一个GifBitmapWrapperStreamResourceDecoder类型的对象,在关键代码3处,这个GifBitmapWrapperStreamResourceDecoder内部有传入了一个GifBitmapWrapperResourceDecoder类型的对象。在创建GifBitmapWrapperResourceDecoder 类型的对象时,在关键代码4处,通过bitmapProvider.getSourceDecoder()创建了一个DataLoadProviderle类型的对象,这个bitmapProvider 又具体是什么类型的对象呢?在解析继续向下分析之前,在回头看看Glide的初始化:
public class Glide {
Glide(Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, Context context, DecodeFormat decodeFormat) {
...
ImageVideoDataLoadProvider imageVideoDataLoadProvider =
new ImageVideoDataLoadProvider(streamBitmapLoadProvider, fileDescriptorLoadProvider);
...
dataLoadProviderRegistry.register(ImageVideoWrapper.class, GifBitmapWrapper.class,
new ImageVideoGifDrawableLoadProvider(imageVideoDataLoadProvider, gifDrawableLoadProvider, bitmapPool));
}
}
可以看到,Glide初始化时,对ImageVideoGifDrawableLoadProvider进行了初始化,并传传入了ImageVideoDataLoadProvider 类型的参数作为ImageVideoGifDrawableLoadProvider的构造方法的第一个参数。所以,ImageVideoGifDrawableLoadProvider 的构造方法的关键代码4处的bitmapProvider就是ImageVideoDataLoadProvider 类型的对象。这样,
bitmapProvider.getSourceDecoder()的代码执行逻辑就跳转到了ImageVideoDataLoadProvider 类的getSourceDecoder()方法中
public class ImageVideoDataLoadProvider implements DataLoadProvider<ImageVideoWrapper, Bitmap> {
private final ImageVideoBitmapDecoder sourceDecoder;
private final ResourceDecoder<File, Bitmap> cacheDecoder;
private final ResourceEncoder<Bitmap> encoder;
private final ImageVideoWrapperEncoder sourceEncoder;
public ImageVideoDataLoadProvider(DataLoadProvider<InputStream, Bitmap> streamBitmapProvider,
DataLoadProvider<ParcelFileDescriptor, Bitmap> fileDescriptorBitmapProvider) {
encoder = streamBitmapProvider.getEncoder();
sourceEncoder = new ImageVideoWrapperEncoder(streamBitmapProvider.getSourceEncoder(),
fileDescriptorBitmapProvider.getSourceEncoder());
cacheDecoder = streamBitmapProvider.getCacheDecoder();
//关键代码
sourceDecoder = new ImageVideoBitmapDecoder(streamBitmapProvider.getSourceDecoder(),
fileDescriptorBitmapProvider.getSourceDecoder());
}
...
@Override
public ResourceDecoder<ImageVideoWrapper, Bitmap> getSourceDecoder() {
return sourceDecoder;
}
...
}
这个方法内部返回的是一个ImageVideoBitmapDecoder类型的对象,不过这个对象在创建时,又调用了streamBitmapProvider.getSourceDecoder(),这个streamBitmapProvider也在Glide类初始化时,传入的,这里就不再带着大家看Glide初始化的源码了,这里的streamBitmapProvider就是StreamBitmapDataLoadProvider类型的,所以代码又跳转到了StreamBitmapDataLoadProvider的getSourceDecoder()方法
public class StreamBitmapDataLoadProvider implements DataLoadProvider<InputStream, Bitmap> {
private final StreamBitmapDecoder decoder;
private final BitmapEncoder encoder;
private final StreamEncoder sourceEncoder;
private final FileToStreamDecoder<Bitmap> cacheDecoder;
public StreamBitmapDataLoadProvider(BitmapPool bitmapPool, DecodeFormat decodeFormat) {
sourceEncoder = new StreamEncoder();
//关键代码
decoder = new StreamBitmapDecoder(bitmapPool, decodeFormat);
encoder = new BitmapEncoder();
cacheDecoder = new FileToStreamDecoder<Bitmap>(decoder);
}
...
@Override
public ResourceDecoder<InputStream, Bitmap> getSourceDecoder() {
return decoder;
}
...
}
StreamBitmapDataLoadProvider的getSourceDecoder()方法内部最后返回的是一个StreamBitmapDecoder类型的对象,这个后面会用到。到这里可以认为ImageVideoGifDrawableLoadProvider类的getCacheDecoder()方法返回的就是一个StreamBitmapDecoder类型的对象。注意只能认为,实际却不是,实际上返回的是FileToStreamDecoder类型的对象。这里这样表述是为了后面分析时,方便理解。
回到DecodeJob类的loadFromCache方法,
class DecodeJob<A, T, Z> {
...
private Resource<T> loadFromCache(Key key) throws IOException {
File cacheFile = diskCacheProvider.getDiskCache().get(key);
if (cacheFile == null) {
return null;
}
Resource<T> result = null;
try {
//关键代码
result = loadProvider.getCacheDecoder().decode(cacheFile, width, height);
} finally {
if (result == null) {
diskCacheProvider.getDiskCache().delete(key);
}
}
return result;
}
...
}
关键代码处 loadProvider.getCacheDecoder()获取的其实就是一个FileToStreamDecoder类型的对象。但是经过前面的分析,FileStreamDecoder内部封装了多层的Decoder,并调用了这个对象的decode方法,经过内部封装的各个Decoder,会最终调用到StreamBitmapDecoder类的decode方法,所以,这也是为什么上面说 loadProvider.getCacheDecoder()获取的对象可以认为是StreamBitmapDecoder类型的对象。
public class StreamBitmapDecoder implements ResourceDecoder<InputStream, Bitmap> {
...
@Override
public Resource<Bitmap> decode(InputStream source, int width, int height) {
Bitmap bitmap = downsampler.decode(source, bitmapPool, width, height, decodeFormat);
return BitmapResource.obtain(bitmap, bitmapPool);
}
...
}
这个方法户返回一个Bitmap对象,这样就将InputStream流数据解码成Bitmap类型的对象了。
这样DecodeJob类的decodeFromSource()方法得到的就是一个Resource类型的对象。下面再次贴出DecodeJob类的decodeFromSource()方法
class DecodeJob<A, T, Z> {
...
public Resource<Z> decodeFromSource() throws Exception {
Resource<T> decoded = decodeSource();
return transformEncodeAndTranscode(decoded);
}
...
private Resource<T> decodeSource() throws Exception {
Resource<T> decoded = null;
try {
long startTime = LogTime.getLogTime();
//关键代码1
final A data = fetcher.loadData(priority);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Fetched data", startTime);
}
if (isCancelled) {
return null;
}
//关键代码2
decoded = decodeFromSourceData(data);
} finally {
fetcher.cleanup();
}
return decoded;
}
...
}
经过层层向上返回,返回到EngineRunnable 的run方法的具体实现:
class EngineRunnable implements Runnable, Prioritized {
...
@Override
public void run() {
if (isCancelled) {
return;
}
Exception exception = null;
Resource<?> resource = null;
try {
//关键代码1
resource = decode();
} 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) {
//关键代码2
onLoadFailed(exception);
} else {
//关键代码3
onLoadComplete(resource);
}
}
...
}
在关键代码1处,这个resource 就是Resource类型的。下面继续分析这个方法,如果recource为null,则执行关键代码2处逻辑,否则执行关键代码3处的逻辑,下面先分析关键代码2处的逻辑,
class EngineRunnable implements Runnable, Prioritized {
...
private void onLoadFailed(Exception e) {
if (isDecodingFromCache()) {
//关键代码1
stage = Stage.SOURCE;
manager.submitForSource(this);
} else {
manager.onException(e);
}
}
...
}
这个方法内部不管是执行if逻辑还是else逻辑,最终都会调用 manager.onException(e),这里的 manager其实就是EngineJob类型的对象。这样代码执行到EngineJob类的onException()方法
class EngineJob implements EngineRunnable.EngineRunnableManager {
...
private static final Handler MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper(), new MainThreadCallback());
@Override
public void onException(final Exception e) {
this.exception = e;
MAIN_THREAD_HANDLER.obtainMessage(MSG_EXCEPTION, this).sendToTarget();
}
...
private void handleExceptionOnMainThread() {
if (isCancelled) {
return;
} else if (cbs.isEmpty()) {
throw new IllegalStateException("Received an exception without any callbacks to notify");
}
hasException = true;
listener.onEngineJobComplete(key, null);
for (ResourceCallback cb : cbs) {
if (!isInIgnoredCallbacks(cb)) {
//关键代码
cb.onException(exception);
}
}
}
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();
} else {
job.handleExceptionOnMainThread();
}
return true;
}
return false;
}
}
}
这个方法内部通过MAIN_THREAD_HANDLER这个handler发送下消息,将代码的执行线程从子线程切换到UI线程。并最终执行到handleExceptionOnMainThread()方法中,在这个方法中的会遍历cbs,并调用其每个元素的onException方法,那这个cbs是什么,cbs其实就是一个ArrayList,它里面存放的是ResourceCallback类型的对象 ,那cbs这个集合是在什么时候存入这些ResourceCallback类型的对象的呢?是在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 engineJob = engineJobFactory.build(key, isMemoryCacheable);
...
engineJob.addCallback(cb);
...
return new LoadStatus(cb, engineJob);
}
那这个Engine的 load方法是在何处调用的呢?
public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallback,ResourceCallback {
@Override
public void onSizeReady(int width, int height) {
...
//注意,调用Engine的load方法,传入的最后一个参数是this,也就是GenericRequest类本身,GenericRequest也实现了ResourceCallback 接口
loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
priority, isMemoryCacheable, diskCacheStrategy, this);
...
}
...
}
所以,EngineJob类的 handleExceptionOnMainThread()方法内部遍历cbs这个集合的内部存放的都是GenericRequest类型的对象,那么调用的就是GenericRequest类的onException()方法,
public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallback,ResourceCallback {
...
@Override
public void onException(Exception e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "load failed", e);
}
status = Status.FAILED;
//TODO: what if this is a thumbnail request?
if (requestListener == null || !requestListener.onException(e, model, target, isFirstReadyResource())) {
setErrorPlaceholder(e);
}
}
...
private void setErrorPlaceholder(Exception e) {
if (!canNotifyStatusChanged()) {
return;
}
Drawable error = model == null ? getFallbackDrawable() : null;
if (error == null) {
error = getErrorDrawable();
}
if (error == null) {
error = getPlaceholderDrawable();
}
target.onLoadFailed(e, error);
}
}
这个方法内部最终会执行到 target.onLoadFailed(e, error);这样代码,这里的target就是前面分析glide.buildImageViewTarget(view, transcodeClass)创建的对象GlideDrawableImageViewTarget类型的对象,这样代码又执行到了GlideDrawableImageViewTarget类的onLoadFailed()方法,这个方式是GlideDrawableImageViewTarget类的父类ImageViewTarget的的方法
public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z> implements GlideAnimation.ViewAdapter {
...
@Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
view.setImageDrawable(errorDrawable);
}
...
}
这个方法中,最终将结果设置到了ImageView上面。到这里分析完了EngineRunnable 的run方法的关键代码2处的逻辑, 下面继续分析关键代码3处的逻辑,具体实现:
class EngineRunnable implements Runnable, Prioritized {
...
@Override
public void run() {
...
if (resource == null) {
//关键代码2
onLoadFailed(exception);
} else {
//关键代码3
onLoadComplete(resource);
}
}
...
private void onLoadComplete(Resource resource) {
manager.onResourceReady(resource);
}
...
}
在关键代码3处,回调用onLoadComplete()方法,这个onLoadComplete()方法内部又调用了EngineJob类的onResourceReady()方法
class EngineJob implements EngineRunnable.EngineRunnableManager {
...
private static final Handler MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper(), new MainThreadCallback());
...
@Override
public void onResourceReady(final Resource<?> resource) {
this.resource = resource;
MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
}
private void handleResultOnMainThread() {
if (isCancelled) {
resource.recycle();
return;
} else if (cbs.isEmpty()) {
throw new IllegalStateException("Received a resource without any callbacks to notify");
}
engineResource = engineResourceFactory.build(resource, isCacheable);
hasResource = true;
// Hold on to resource for duration of request so we don't recycle it in the middle of notifying if it
// synchronously released by one of the callbacks.
engineResource.acquire();
listener.onEngineJobComplete(key, engineResource);
for (ResourceCallback cb : cbs) {
if (!isInIgnoredCallbacks(cb)) {
engineResource.acquire();
cb.onResourceReady(engineResource);
}
}
// Our request is complete, so we can release the resource.
engineResource.release();
}
private void handleResultOnMainThread() {
if (isCancelled) {
resource.recycle();
return;
} else if (cbs.isEmpty()) {
throw new IllegalStateException("Received a resource without any callbacks to notify");
}
engineResource = engineResourceFactory.build(resource, isCacheable);
hasResource = true;
// Hold on to resource for duration of request so we don't recycle it in the middle of notifying if it
// synchronously released by one of the callbacks.
engineResource.acquire();
listener.onEngineJobComplete(key, engineResource);
for (ResourceCallback cb : cbs) {
if (!isInIgnoredCallbacks(cb)) {
engineResource.acquire();
//关键代码
cb.onResourceReady(engineResource);
}
}
// Our request is complete, so we can release the resource.
engineResource.release();
}
...
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();
} else {
job.handleExceptionOnMainThread();
}
return true;
}
return false;
}
}
}
这个方法内部会通过handler从子线程切换到UI线程,并最终执行到handleResultOnMainThread() 方法,在handleResultOnMainThread() 方法内部也是遍历cbs这个ArrayList集合,并调用集合中的元素的onResourceReady()方法,前面分析失败时,就知道cbs集合中的 元素就是
GenericRequest类型的对象.所以代码执行到GenericRequest类的onResourceReady()方法
public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallback,ResourceCallback {
...
@Override
public void onResourceReady(Resource<?> resource) {
if (resource == null) {
onException(new Exception("Expected to receive a Resource<R> with an object of " + transcodeClass
+ " inside, but instead got null."));
return;
}
Object received = resource.get();
if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
releaseResource(resource);
onException(new Exception("Expected to receive an object of " + transcodeClass
+ " but instead got " + (received != null ? received.getClass() : "") + "{" + received + "}"
+ " inside Resource{" + resource + "}."
+ (received != null ? "" : " "
+ "To indicate failure return a null Resource object, "
+ "rather than a Resource object containing null data.")
));
return;
}
if (!canSetResource()) {
releaseResource(resource);
// We can't set the status to complete before asking canSetResource().
status = Status.COMPLETE;
return;
}
onResourceReady(resource, (R) received);
}
/**
* Internal {@link #onResourceReady(Resource)} where arguments are known to be safe.
*
* @param resource original {@link Resource}, never <code>null</code>
* @param result object returned by {@link Resource#get()}, checked for type and never <code>null</code>
*/
private void onResourceReady(Resource<?> resource, R result) {
// We must call isFirstReadyResource before setting status.
boolean isFirstResource = isFirstReadyResource();
status = Status.COMPLETE;
this.resource = resource;
if (requestListener == null || !requestListener.onResourceReady(result, model, target, loadedFromMemoryCache,
isFirstResource)) {
GlideAnimation<R> animation = animationFactory.build(loadedFromMemoryCache, isFirstResource);
//关键代码
target.onResourceReady(result, animation);
}
notifyLoadSuccess();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("Resource ready in " + LogTime.getElapsedMillis(startTime) + " size: "
+ (resource.getSize() * TO_MEGABYTE) + " fromCache: " + loadedFromMemoryCache);
}
}
...
}
GenericRequest类的onResourceReady()方法内部调用其重载方法,并在这个重载方法内部最终执行
target.onResourceReady(result, animation);
这行代码,前面已经分析过,这个target就是GlideDrawableImageViewTarget类型的对象,所以代码执行到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);
this.resource = resource;
resource.setLoopCount(maxLoopCount);
resource.start();
}
...
}
这个方法内部,在关键代码处,调用其父类的ImageViewTarget的onResourceReady()方法
@Override
public void onResourceReady(Z resource, GlideAnimation<? super Z> glideAnimation) {
if (glideAnimation == null || !glideAnimation.animate(resource, this)) {
setResource(resource);
}
}
这个方法内部又调用恶劣子类的setResource()方法
public class GlideDrawableImageViewTarget extends ImageViewTarget<GlideDrawable>
...
@Override
protected void setResource(GlideDrawable resource) {
view.setImageDrawable(resource);
}
...
}
最终还是调用了在into方法中传入的imageview的setImageDrawable方法,将图片设置到了ImageView上面显示出来。
到这里,终于将Glide.with(this).load(url).into(iv);这样代码的调用过程分析完毕,只是分析了部分逻辑,如果图片已经缓存的逻辑,还未分析,加gif动图的 过程也未分析,读者有兴趣,可以自己去分析,分析过程中,笔者也是有几次差点被源码绕晕了,不过还好最终还是坚持分析完了,在分析过程中,主要是很多成员变量都是接口类型的,需要找到这些成员变量的具体类型,才能继续向下分析,但是这些成员变量的赋值很多是在Glide的初始化的时候赋值的,往往为了找到一个变量的赋值,一步一步的跟进,最后跟进到了Glided的初始化过程,后面在回过头继续分析时,要想很久,是从哪里开始继续分析,建议读者在分析时,结合使用StartUML这个工具,效果可能好点。