借鉴自郭霖http://blog.csdn.net/guolin_blog/article/details/53939176,学着理一遍
这里对Glide源码的研究方向是,URL路线
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
RequestManager fragmentGet(Context context,android.app.FragmentManager fm) {
RequestManagerFragment current =getRequestManagerFragment(fm);
RequestManager requestManager =current.getRequestManager();
if (requestManager== null) {
requestManager = newRequestManager(context, current.getLifecycle(),current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
SupportRequestManagerFragmentgetSupportRequestManagerFragment(final FragmentManagerfm) {
SupportRequestManagerFragment current =(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current =pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
current = newSupportRequestManagerFragment();
pendingSupportRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current,FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER,fm).sendToTarget();
}
}
return current;
}
RequestManager supportFragmentGet(Contextcontext, FragmentManager fm) {
SupportRequestManagerFragment current =getSupportRequestManagerFragment(fm);
RequestManager requestManager =current.getRequestManager();
if (requestManager== null) {
requestManager = newRequestManager(context, current.getLifecycle(),current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
往Activity中加入一个碎片,通过碎片的生命周期来监听Activity的onDestory,进行加载图片的取消工作
public RequestManager get(FragmentActivityactivity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
FragmentManager fm =activity.getSupportFragmentManager();
return supportFragmentGet(activity, fm);
}
}
非主线程中使用Glide,不管传入Activity还是Fragment,都会被当成Application来处理
with:主要为了得到RequestManager对象
疑惑:RequestManager对象有缓存起来吗
load:是对RequestManager对象的操作,选择一个URL入手
简化后代码如下
publicclassRequestManagerimplementsLifecycleListener {
...
public DrawableTypeRequest<String>load(String string) {
return (DrawableTypeRequest<String>)fromString().load(string);
}
public DrawableTypeRequest<String>fromString() {
return loadGeneric(String.class);
}
private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass){
ModelLoader<T, InputStream> streamModelLoader = Glide.buildStreamModelLoader(modelClass,context);
ModelLoader<T, ParcelFileDescriptor> fileDescriptorModelLoader =
Glide.buildFileDescriptorModelLoader(modelClass, context);
//获取ModelLoader(用于加载图片)对象,传入不同类型的参数会得到不同类型的ModelLoader,URL代表传入的是String,得到的是StreamStringLoader
if (modelClass != null && streamModelLoader == null && fileDescriptorModelLoader == null) {
thrownew IllegalArgumentException("Unknown type " + modelClass + ".You must provide a Model of a type for"
+ " which there is a registeredModelLoader, if you are using a custom model, you must first call"
+ " Glide#register with aModelLoaderFactory for your custom model class");
}
return optionsApplier.apply(
new DrawableTypeRequest<T>(modelClass,streamModelLoader, fileDescriptorModelLoader, context,
glide, requestTracker,lifecycle, optionsApplier));
}
...
}
看一下loadGeneric的返回值也是fromJson的返回值DrawableTypeRequest,别管这么多参数了
简化后的代码
publicclassDrawableTypeRequest<ModelType> extendsDrawableRequestBuilder<ModelType> implementsDownloadOptions {
privatefinal ModelLoader<ModelType, InputStream>streamModelLoader;
privatefinal ModelLoader<ModelType,ParcelFileDescriptor> fileDescriptorModelLoader;
privatefinal RequestManager.OptionsApplieroptionsApplier;
privatestatic <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) {
returnnull;
}
if (transcoder == null) {
transcoder =glide.buildTranscoder(resourceClass, transcodedClass);
}
DataLoadProvider<ImageVideoWrapper, Z> dataLoadProvider =glide.buildDataProvider(ImageVideoWrapper.class,
resourceClass);
ImageVideoModelLoader<A> modelLoader = newImageVideoModelLoader<A>(streamModelLoader,
fileDescriptorModelLoader);
returnnew FixedLoadProvider<A, ImageVideoWrapper,Z, R>(modelLoader, transcoder, dataLoadProvider);
}
DrawableTypeRequest(Class<ModelType> modelClass,ModelLoader<ModelType, InputStream> streamModelLoader,
ModelLoader<ModelType,ParcelFileDescriptor> fileDescriptorModelLoader, Context context, Glideglide,
RequestTracker requestTracker,Lifecycle lifecycle, RequestManager.OptionsApplier optionsApplier) {
super(context, modelClass,
buildProvider(glide, streamModelLoader,fileDescriptorModelLoader, GifBitmapWrapper.class,
GlideDrawable.class, null),
glide, requestTracker,lifecycle);
this.streamModelLoader = streamModelLoader;
this.fileDescriptorModelLoader =fileDescriptorModelLoader;
this.optionsApplier = optionsApplier;
}
public BitmapTypeRequest<ModelType>asBitmap() {
return optionsApplier.apply(new BitmapTypeRequest<ModelType>(this, streamModelLoader,
fileDescriptorModelLoader,optionsApplier));
}
public GifTypeRequest<ModelType> asGif(){
return optionsApplier.apply(new GifTypeRequest<ModelType>(this, streamModelLoader, optionsApplier));
}
...
}
asBitmap、asGif,强行指定是静图还是动图,他们分别创建一个BitmapTypeRequest和GifTypeRequest,如果没有进行强制指定的话,那默认就是使用DrawableTypeRequest。
fromString.load就是DrawableTypeRequest.load,子类里没有,所以是DrawableRequestBuilder.load,看一下DrawableRequestBuilder类,包含了许多api
publicclassDrawableRequestBuilder<ModelType>
extendsGenericRequestBuilder<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable>
implementsBitmapOptions, DrawableOptions {
DrawableRequestBuilder(Context context, Class<ModelType>modelClass,
LoadProvider<ModelType,ImageVideoWrapper, GifBitmapWrapper, GlideDrawable> loadProvider, Glideglide,
RequestTracker requestTracker,Lifecycle lifecycle) {
super(context, modelClass, loadProvider,GlideDrawable.class, glide, requestTracker, lifecycle);
// Default toanimating.
crossFade();
}
public DrawableRequestBuilder<ModelType>thumbnail(
DrawableRequestBuilder<?>thumbnailRequest) {
super.thumbnail(thumbnailRequest);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>thumbnail(
GenericRequestBuilder<?, ?, ?,GlideDrawable> thumbnailRequest) {
super.thumbnail(thumbnailRequest);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>thumbnail(float sizeMultiplier) {
super.thumbnail(sizeMultiplier);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>sizeMultiplier(float sizeMultiplier) {
super.sizeMultiplier(sizeMultiplier);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>decoder(ResourceDecoder<ImageVideoWrapper, GifBitmapWrapper> decoder) {
super.decoder(decoder);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>cacheDecoder(ResourceDecoder<File, GifBitmapWrapper> cacheDecoder) {
super.cacheDecoder(cacheDecoder);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>encoder(ResourceEncoder<GifBitmapWrapper> encoder) {
super.encoder(encoder);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>priority(Priority priority) {
super.priority(priority);
returnthis;
}
public DrawableRequestBuilder<ModelType>transform(BitmapTransformation... transformations) {
return bitmapTransform(transformations);
}
public DrawableRequestBuilder<ModelType>centerCrop() {
returntransform(glide.getDrawableCenterCrop());
}
public DrawableRequestBuilder<ModelType>fitCenter() {
returntransform(glide.getDrawableFitCenter());
}
public DrawableRequestBuilder<ModelType>bitmapTransform(Transformation<Bitmap>... bitmapTransformations) {
GifBitmapWrapperTransformation[] transformations =
newGifBitmapWrapperTransformation[bitmapTransformations.length];
for (int i = 0; i < bitmapTransformations.length; i++) {
transformations[i] = new GifBitmapWrapperTransformation(glide.getBitmapPool(),bitmapTransformations[i]);
}
return transform(transformations);
}
@Override
public DrawableRequestBuilder<ModelType>transform(Transformation<GifBitmapWrapper>... transformation) {
super.transform(transformation);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>transcoder(
ResourceTranscoder<GifBitmapWrapper, GlideDrawable> transcoder) {
super.transcoder(transcoder);
returnthis;
}
publicfinal DrawableRequestBuilder<ModelType>crossFade() {
super.animate(newDrawableCrossFadeFactory<GlideDrawable>());
returnthis;
}
public DrawableRequestBuilder<ModelType>crossFade(int duration) {
super.animate(newDrawableCrossFadeFactory<GlideDrawable>(duration));
returnthis;
}
public DrawableRequestBuilder<ModelType>crossFade(int animationId, int duration) {
super.animate(newDrawableCrossFadeFactory<GlideDrawable>(context, animationId,
duration));
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>dontAnimate() {
super.dontAnimate();
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>animate(ViewPropertyAnimation.Animator animator) {
super.animate(animator);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>animate(int animationId) {
super.animate(animationId);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>placeholder(int resourceId) {
super.placeholder(resourceId);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>placeholder(Drawable drawable) {
super.placeholder(drawable);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>fallback(Drawable drawable) {
super.fallback(drawable);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>fallback(int resourceId) {
super.fallback(resourceId);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>error(int resourceId) {
super.error(resourceId);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>error(Drawable drawable) {
super.error(drawable);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>listener(
RequestListener<? super ModelType, GlideDrawable>requestListener) {
super.listener(requestListener);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>diskCacheStrategy(DiskCacheStrategy strategy) {
super.diskCacheStrategy(strategy);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>skipMemoryCache(boolean skip) {
super.skipMemoryCache(skip);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>override(int width, int height) {
super.override(width, height);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>sourceEncoder(Encoder<ImageVideoWrapper> sourceEncoder) {
super.sourceEncoder(sourceEncoder);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>dontTransform() {
super.dontTransform();
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>signature(Key signature) {
super.signature(signature);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>load(ModelType model) {
super.load(model);
returnthis;
}
@Override
public DrawableRequestBuilder<ModelType>clone() {
return (DrawableRequestBuilder<ModelType>) super.clone();
}
@Override
public Target<GlideDrawable>into(ImageView view) {
returnsuper.into(view);
}
@Override
void applyFitCenter() {
fitCenter();
}
@Override
void applyCenterCrop() {
centerCrop();
}
}
看到这里,我觉得继承架构需要理一理
看看GenericRequestBuilder.into
public Target<TranscodeType> into(ImageViewview) {
Util.assertMainThread();
if (view == null) {
thrownew IllegalArgumentException("You must pass in a non nullView");
}
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.
}
}
return into(glide.buildImageViewTarget(view,transcodeClass));
}
看buildImageViewTarget
<R> Target<R>buildImageViewTarget(ImageView imageView, Class<R> transcodedClass) {
returnimageViewTargetFactory.buildTarget(imageView, transcodedClass);
}
看buildTarget
publicclassImageViewTargetFactory {
@SuppressWarnings("unchecked")
public <Z> Target<Z>buildTarget(ImageView view, Class<Z> clazz) {
if(GlideDrawable.class.isAssignableFrom(clazz)) {
return (Target<Z>) new GlideDrawableImageViewTarget(view);
} elseif (Bitmap.class.equals(clazz)) {
return (Target<Z>) new BitmapImageViewTarget(view);
} elseif (Drawable.class.isAssignableFrom(clazz)) {
return (Target<Z>) new DrawableImageViewTarget(view);//一般用不到
} else {
thrownew IllegalArgumentException("Unhandled class: " + clazz
+ ", try.as*(Class).transcode(ResourceTranscoder)");
}
}
}
这个class参数从哪里传来?
如果使用asBitmap,这里会构建出BitmapImageViewTarget对象,否则构建出的都是GlideDrawableImageViewTarget对象
看看GenericRequestBuilder.into最后一行的into
public <Y extendsTarget<TranscodeType>> Y into(Y target) {
Util.assertMainThread();
if (target == null) {
thrownew IllegalArgumentException("You must pass in a non nullTarget");
}
if (!isModelSet) {
thrownew IllegalArgumentException("You must first set a model (try#load())");
}
Request previous = target.getRequest();
if (previous != null) {
previous.clear();
requestTracker.removeRequest(previous);
previous.recycle();
}
Request request = buildRequest(target);//构建Request
target.setRequest(request);
lifecycle.addListener(target);
requestTracker.runRequest(request);//执行这个Request
return target;
}
最后需要梳理一遍流程
Request是用来发出加载图片请求的,看看buildRequest方法
private RequestbuildRequest(Target<TranscodeType> target) {
if (priority == null) {
priority = Priority.NORMAL;
}
return buildRequestRecursive(target, null);
}
private RequestbuildRequestRecursive(Target<TranscodeType> target,ThumbnailRequestCoordinator parentCoordinator) {//90%的代码在处理缩略图
if (thumbnailRequestBuilder != null) {
if (isThumbnailBuilt) {
thrownew IllegalStateException("You cannot use a request as both the main request and a thumbnail,"
+ "consider using clone() on therequest(s) passed to thumbnail()");
}
// Recursivecase: contains a potentially recursive thumbnail request builder.
if(thumbnailRequestBuilder.animationFactory.equals(NoAnimation.getFactory())) {
thumbnailRequestBuilder.animationFactory= animationFactory;
}
if (thumbnailRequestBuilder.priority == null) {
thumbnailRequestBuilder.priority =getThumbnailPriority();
}
if (Util.isValidDimensions(overrideWidth,overrideHeight)
&&!Util.isValidDimensions(thumbnailRequestBuilder.overrideWidth,
thumbnailRequestBuilder.overrideHeight)) {
thumbnailRequestBuilder.override(overrideWidth, overrideHeight);
}
ThumbnailRequestCoordinator coordinator = newThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest = obtainRequest(target, sizeMultiplier, priority,coordinator);
// Guard againstinfinite recursion.
isThumbnailBuilt = true;
// Recursivelygenerate thumbnail requests.
Request thumbRequest =thumbnailRequestBuilder.buildRequestRecursive(target, coordinator);
isThumbnailBuilt = false;
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
} elseif (thumbSizeMultiplier != null) {
// Base case:thumbnail multiplier generates a thumbnail request, but cannot recurse.
ThumbnailRequestCoordinator coordinator = newThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest = obtainRequest(target, sizeMultiplier, priority,coordinator);
Request thumbnailRequest = obtainRequest(target, thumbSizeMultiplier,getThumbnailPriority(), coordinator);
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else {
// Base case: nothumbnail.
return obtainRequest(target, sizeMultiplier,priority, parentCoordinator);//通过obtainRequest方法,获取Request对象,内部又调用了GenericRequest.obtain方法
}
}
private RequestobtainRequest(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);
}
看一下GenericRequest.obtain
publicfinalclassGenericRequest<A, T, Z, R> implementsRequest, SizeReadyCallback,
ResourceCallback {
...
publicstatic <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,
RequestCoordinatorrequestCoordinator,
Engine engine,
Transformation<Z>transformation,
Class<R> transcodeClass,
boolean isMemoryCacheable,
GlideAnimationFactory<R>animationFactory,
int overrideWidth,
int overrideHeight,
DiskCacheStrategydiskCacheStrategy) {
@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>();
}
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;
}
...
}
runRequest方法,Request的执行处
publicvoid runRequest(Request request) {
requests.add(request);
if (!isPaused) {
request.begin();//如果不是暂停状态,执行Request
} else {
pendingRequests.add(request);//否则把Request添加到等待队列中,等暂停状态解除了再执行
}
}
判断Glide是否处于暂停状态
GenericRequest.begin
@Override
publicvoid begin() {
startTime = LogTime.getLogTime();
if (model == null) {//model是我们传入的URL地址,如果是null,最后会调用到setErrorPlaceholder()
onException(null);
return;
}
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth,overrideHeight)) {//加载实际图片,如果你用override为图片指定了宽高
onSizeReady(overrideWidth, overrideHeight);
} else {//没指定就计算
target.getSize(this);
}
if (!isComplete() && !isFailed()&& canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable());//loading占位图
}
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finishedrun method in " +LogTime.getElapsedMillis(startTime));
}
}
setErrorPlaceholder
privatevoid 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);
}
onLoadFailed
publicabstractclassImageViewTarget<Z> extendsViewTarget<ImageView, Z> implementsGlideAnimation.ViewAdapter {
...
@Override
publicvoid onLoadStarted(Drawable placeholder) {
view.setImageDrawable(placeholder);
}
@Override
publicvoid onLoadFailed(Exception e, DrawableerrorDrawable) {
view.setImageDrawable(errorDrawable);
}
...
}
onSizeReady
@Override
publicvoid onSizeReady(int width, int height) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("GotonSizeReady in " +LogTime.getElapsedMillis(startTime));
}
if (status != Status.WAITING_FOR_SIZE) {
return;
}
status = Status.RUNNING;
width = Math.round(sizeMultiplier * width);
height = Math.round(sizeMultiplier * height);
ModelLoader<A, T> modelLoader = loadProvider.getModelLoader();
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("finishedsetup for calling load in " + LogTime.getElapsedMillis(startTime));
}
loadedFromMemoryCache = true;
loadStatus = engine.load(signature, width, height, dataFetcher,loadProvider, transformation, transcoder,
priority, isMemoryCacheable,diskCacheStrategy, this);
loadedFromMemoryCache = resource != null;
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finishedonSizeReady in " +LogTime.getElapsedMillis(startTime));
}
}
ModelLoader是什么?在DrawableTypeRequest构造函数中,调用了buildProvider,并把streamModelLoader和fileDescriptorModelLoader等参数传入到这个方法中,这两个ModelLoader是在loadGeneric方法中构建出来的。
buildProvider中调用了glide.buildTranscoder来构建一个ResourceTranscoder,它是用于对图片进行转码的,它是一个接口,这里实际会构建出一个GifBitmapWrapperDrawableTranscoder对象
上文中后面又调用了glide.buildDataProvider来构建一个DataLoadProvider,用于对图片进行编解码的,DataLoadProvider是一个接口,这里实际会构建出一个ImageVideoGifDrawableLoadProvider对象。
下面new了一个ImageVideoModelLoader的实例,并把loadGeneric()方法中构建的两个ModelLoader封装到了ImageVideoModelLoader当中
下面new出一个FixedLoadProvider,并把刚才构建的出来的GifBitmapWrapperDrawableTranscoder、ImageVideoModelLoader、ImageVideoGifDrawableLoadProvider都封装进去,这个也就是onSizeReady()方法中的loadProvider了
上面还有getResourceFetcher方法
getResourceFetcher
publicclassImageVideoModelLoader<A> implementsModelLoader<A, ImageVideoWrapper> {
privatestaticfinal String TAG = "IVML";
privatefinal ModelLoader<A, InputStream>streamLoader;
privatefinal ModelLoader<A, ParcelFileDescriptor>fileDescriptorLoader;
public ImageVideoModelLoader(ModelLoader<A,InputStream> streamLoader,
ModelLoader<A,ParcelFileDescriptor> fileDescriptorLoader) {
if (streamLoader == null && fileDescriptorLoader == null) {
thrownew NullPointerException("At least one of streamLoader and fileDescriptorLoader must be nonnull");
}
this.streamLoader = streamLoader;
this.fileDescriptorLoader =fileDescriptorLoader;
}
@Override
public DataFetcher<ImageVideoWrapper>getResourceFetcher(A model, int width, int height) {
DataFetcher<InputStream> streamFetcher = null;
if (streamLoader != null) {
streamFetcher = streamLoader.getResourceFetcher(model, width, height);
}
DataFetcher<ParcelFileDescriptor> fileDescriptorFetcher = null;
if (fileDescriptorLoader != null) {
fileDescriptorFetcher =fileDescriptorLoader.getResourceFetcher(model, width, height);
}
if (streamFetcher != null || fileDescriptorFetcher != null) {
returnnew ImageVideoFetcher(streamFetcher, fileDescriptorFetcher);
} else {
returnnull;
}
}
static class ImageVideoFetcher implementsDataFetcher<ImageVideoWrapper> {
privatefinal DataFetcher<InputStream>streamFetcher;
privatefinal DataFetcher<ParcelFileDescriptor> fileDescriptorFetcher;
publicImageVideoFetcher(DataFetcher<InputStream> streamFetcher,
DataFetcher<ParcelFileDescriptor> fileDescriptorFetcher) {
this.streamFetcher = streamFetcher;
this.fileDescriptorFetcher =fileDescriptorFetcher;
}
...
}
}
先调用streamLoader.getResourceFetcher()方法获取一个DataFetcher,这个streamLoader是在loadGeneric方法中构建出来的StreamStringLoader,streamLoader.getResourceFetcher会返回HttpUrlFetcher对象
下面new出了一个ImageVideoFetcher对象,并把获得的HttpUrlFetcher对象传进去
所以本方法是返回ImageVideoFetcher方法
onSizeReady中下面又调用了engine.load,把刚才获得的ImageVideoFetcher、GifBitmapWrapperDrawableTranscoder等等一系列的值一起传入
看一下engine.load
publicclassEngineimplementsEngineJobListener,
MemoryCache.ResourceRemovedListener,
EngineResource.ResourceListener {
...
public <T, Z, R> LoadStatus load(Keysignature, int width, int height, DataFetcher<T> fetcher,
DataLoadProvider<T, Z>loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z,R> transcoder,
Priority priority, boolean isMemoryCacheable, DiskCacheStrategydiskCacheStrategy, 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);
}
returnnull;
}
EngineResource<?> active = loadFromActiveResources(key,isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from activeresources", startTime,key);
}
returnnull;
}
EngineJob current = jobs.get(key);
if (current != null) {
current.addCallback(cb);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
returnnew LoadStatus(cb, current);
}
EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);
DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width,height, fetcher, loadProvider, transformation,
transcoder, diskCacheProvider,diskCacheStrategy, priority);
EngineRunnable runnable = newEngineRunnable(engineJob, decodeJob, priority);
jobs.put(key, engineJob);
engineJob.addCallback(cb);
engineJob.start(runnable);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Started new load", startTime, key);
}
returnnew LoadStatus(cb, engineJob);
}
...
}
EngineJob engineJob =engineJobFactory.build(key, isMemoryCacheable);构建了一个EngineJob,主要作用是开启线程,为异步加载图片做准备
下面创建了一个DecodeJob对象,这个对象负责的任务很多
下面创建了EngineRunnable对象,并在下面调用了EngineJob.start来运行EngineRunnable对象,这使得EngineRunnable得以在子线程中运行
EngineRunnable的run
@Override
publicvoid run() {
if (isCancelled) {
return;
}
Exception exception = null;
Resource<?> resource = null;
try {
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) {
onLoadFailed(exception);
} else {
onLoadComplete(resource);
}
}
看一下decode方法
private Resource<?> decode() throws Exception {
if (isDecodingFromCache()) {//如果缓存了
return decodeFromCache();
} else {
return 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();
final A data = fetcher.loadData(priority);//这里获取了ImageVideoWrapper
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Fetched data", startTime);
}
if (isCancelled) {
returnnull;
}
decoded = decodeFromSourceData(data);// ImageVideoWrapper传入decodeFromSourceData// decodeFromSourceData得到GifBitmapWrapperResourceDecoder这个对象,调用这个对象进行一个解码
} finally {
fetcher.cleanup();
}
return decoded;
}
...
}
分成两步
decodeSource()获取一个Resourse对象
调用transformEncodeAndTranscode()方法来处理这个Resource对象
decodeSource中调用了fetcher.loadData,fetcher就是onSizeReady中的ImageVideoFetcher对象
fetcher.loadData
@Override
public ImageVideoWrapperloadData(Priority priority) throws Exception {
InputStream is = null;
if (streamFetcher != null) {
try {
is =streamFetcher.loadData(priority);
} catch (Exception e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Exception fetching input stream,trying ParcelFileDescriptor", e);
}
if (fileDescriptorFetcher == null) {
throw e;
}
}
}
ParcelFileDescriptor fileDescriptor = null;
if (fileDescriptorFetcher != null) {
try {
fileDescriptor =fileDescriptorFetcher.loadData(priority);
} catch (Exception e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Exception fetchingParcelFileDescriptor", e);
}
if (is == null) {
throw e;
}
}
}
returnnew ImageVideoWrapper(is, fileDescriptor);// HttpUrlFetcher.loadData,获取输入流,作为参数,返回一个ImageVideoWrapper参数
}
下面又会调用HttpUrlFetcher的loadData方法
HttpUrlFetcher.loadData
publicclassHttpUrlFetcherimplementsDataFetcher<InputStream> {
...
@Override
public InputStream loadData(Priority priority)throws Exception {
return loadDataWithRedirects(glideUrl.toURL(), 0/*redirects*/, null/*lastUrl*/, glideUrl.getHeaders());
}
private InputStream loadDataWithRedirects(URLurl, int redirects, URL lastUrl, Map<String,String> headers)
throws IOException {
if (redirects >= MAXIMUM_REDIRECTS) {
thrownew IOException("Toomany (> " +MAXIMUM_REDIRECTS + ")redirects!");
} else {
try {
if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
thrownew IOException("Inre-direct loop");
}
} catch (URISyntaxException e) {
// Do nothing, this is best effort.
}
}
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);
urlConnection.connect();
if (isCancelled) {
returnnull;
}
finalint statusCode = urlConnection.getResponseCode();
if (statusCode / 100 == 2) {
returngetStreamForSuccessfulRequest(urlConnection);
} elseif (statusCode / 100 == 3) {
String redirectUrlString =urlConnection.getHeaderField("Location");
if (TextUtils.isEmpty(redirectUrlString)) {
thrownew IOException("Receivedempty or null redirect url");
}
URL redirectUrl = new URL(url, redirectUrlString);
return loadDataWithRedirects(redirectUrl,redirects + 1, url, headers);
} else {
if (statusCode == -1) {
thrownew IOException("Unableto retrieve response code from HttpUrlConnection.");
}
thrownew IOException("Requestfailed " + statusCode + ": " + urlConnection.getResponseMessage());
}
}
private InputStreamgetStreamForSuccessfulRequest(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;
}
...
}
decodeFromSourceData
private Resource<T> decodeFromSourceData(Adata) throws IOException {
final Resource<T> decoded;
if (diskCacheStrategy.cacheSource()) {
decoded = cacheAndDecodeSourceData(data);
} else {
long startTime = LogTime.getLogTime();
decoded = loadProvider.getSourceDecoder().decode(data, width, height);//loadProvider就是在onSizeReady中得到的FixedLoadProvider,getSourceDecoder得到的是一个GifBitmapWrapperResourceDecoder对象,要调用这个对象的decode方法来进行一个解码
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Decoded from source", startTime);
}
}
return decoded;
}
GifBitmapWrapperResourceDecoder
publicclassGifBitmapWrapperResourceDecoderimplementsResourceDecoder<ImageVideoWrapper, GifBitmapWrapper> {
...
@SuppressWarnings("resource")
// @see ResourceDecoder.decode
@Override
public Resource<GifBitmapWrapper>decode(ImageVideoWrapper source, int width, int height) throws IOException {
ByteArrayPool pool = ByteArrayPool.get();
byte[] tempBytes = pool.getBytes();
GifBitmapWrapper wrapper = null;
try {
wrapper = decode(source, width,height, tempBytes);
} finally {
pool.releaseBytes(tempBytes);
}
return wrapper != null ? new GifBitmapWrapperResource(wrapper) : null;
}
private GifBitmapWrapperdecode(ImageVideoWrapper source, int width, int height, byte[] bytes) throws IOException {
final GifBitmapWrapper result;
if (source.getStream() != null) {
result = decodeStream(source, width,height, bytes);//从服务器中返回的流读取数据,会从流中先读取2个字节的数据,来判断是gif图还是静图,如果是gif,就调用decodeGifWrapper来进行解码,如果是静图就调用decodeBitmapWrapper来进行解码
} else {
result =decodeBitmapWrapper(source, width, height);
}
return result;
}
private GifBitmapWrapperdecodeStream(ImageVideoWrapper source, int width, int height, byte[] bytes)
throws IOException {
InputStream bis = streamFactory.build(source.getStream(), bytes);
bis.mark(MARK_LIMIT_BYTES);
ImageHeaderParser.ImageType type = parser.parse(bis);
bis.reset();
GifBitmapWrapper result = null;
if (type ==ImageHeaderParser.ImageType.GIF) {
result = decodeGifWrapper(bis,width, height);
}
// Decoding the gifmay fail even if the type matches.
if (result == null) {
// We can only reset the bufferedInputStream, so to start from the beginning of the stream, we need to
// pass in a new source containing thebuffered stream rather than the original stream.
ImageVideoWrapper forBitmapDecoder= new ImageVideoWrapper(bis,source.getFileDescriptor());
result =decodeBitmapWrapper(forBitmapDecoder, width, height);
}
return result;
}
private GifBitmapWrapperdecodeBitmapWrapper(ImageVideoWrapper toDecode, int width, int height) throws IOException {
GifBitmapWrapper result = null;
Resource<Bitmap> bitmapResource = bitmapDecoder.decode(toDecode,width, height);// bitmapDecoder是一个ImageVideoBitmapDecoder对象
if (bitmapResource != null) {
result = new GifBitmapWrapper(bitmapResource, null);
}
return result;
}
...
}
ImageVideoBitmapDecoder
publicclassImageVideoBitmapDecoderimplementsResourceDecoder<ImageVideoWrapper, Bitmap> {
privatefinal ResourceDecoder<InputStream, Bitmap>streamDecoder;
privatefinal ResourceDecoder<ParcelFileDescriptor,Bitmap> fileDescriptorDecoder;
publicImageVideoBitmapDecoder(ResourceDecoder<InputStream, Bitmap>streamDecoder,
ResourceDecoder<ParcelFileDescriptor, Bitmap>fileDescriptorDecoder) {
this.streamDecoder = streamDecoder;
this.fileDescriptorDecoder =fileDescriptorDecoder;
}
@Override
public Resource<Bitmap>decode(ImageVideoWrapper source, int width, int height) throws IOException {
Resource<Bitmap> result = null;
InputStream is = source.getStream();//获取到服务器返回的输入流
if (is != null) {
try {
result =streamDecoder.decode(is, width, height);//对这个输入流进行解码,streamDecoder是一个StreamBitmapDecoder对象
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Failed to load image from stream,trying FileDescriptor", e);
}
}
}
if (result == null) {
ParcelFileDescriptor fileDescriptor= source.getFileDescriptor();
if (fileDescriptor != null) {
result = fileDescriptorDecoder.decode(fileDescriptor,width, height);
}
}
return result;
}
...
}
StreamBitmapDecoder
publicclassStreamBitmapDecoderimplementsResourceDecoder<InputStream, Bitmap> {
...
privatefinal Downsampler downsampler;
private BitmapPool bitmapPool;
private DecodeFormat decodeFormat;
public StreamBitmapDecoder(Downsamplerdownsampler, BitmapPool bitmapPool, DecodeFormat decodeFormat) {
this.downsampler = downsampler;
this.bitmapPool = bitmapPool;
this.decodeFormat = decodeFormat;
}
@Override
public Resource<Bitmap>decode(InputStream source, int width, int height) {
Bitmap bitmap = downsampler.decode(source, bitmapPool, width, height,decodeFormat);//decode取得我们要的bitmap
return BitmapResource.obtain(bitmap,bitmapPool);//obtain方法把bitmap包装成Resource<Bitmap>
}
...
}
Downsampler
publicabstractclassDownsamplerimplementsBitmapDecoder<InputStream> {
...
@Override
public Bitmap decode(InputStream is,BitmapPool pool, int outWidth, int outHeight, DecodeFormat decodeFormat) {
final ByteArrayPool byteArrayPool =ByteArrayPool.get();
finalbyte[] bytesForOptions =byteArrayPool.getBytes();
finalbyte[] bytesForStream =byteArrayPool.getBytes();
final BitmapFactory.Options options =getDefaultOptions();
RecyclableBufferedInputStream bufferedStream = new RecyclableBufferedInputStream(
is, bytesForStream);
ExceptionCatchingInputStreamexceptionStream =
ExceptionCatchingInputStream.obtain(bufferedStream);
MarkEnforcingInputStream invalidatingStream = new MarkEnforcingInputStream(exceptionStream);
try {
exceptionStream.mark(MARK_POSITION);
int orientation = 0;
try {
orientation = newImageHeaderParser(exceptionStream).getOrientation();
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Cannot determine the imageorientation from header", e);
}
} finally {
try {
exceptionStream.reset();
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Cannot reset the inputstream", e);
}
}
}
options.inTempStorage =bytesForOptions;
finalint[] inDimens = getDimensions(invalidatingStream, bufferedStream, options);
finalint inWidth = inDimens[0];
finalint inHeight = inDimens[1];
finalint degreesToRotate =TransformationUtils.getExifOrientationDegrees(orientation);
finalint sampleSize = getRoundedSampleSize(degreesToRotate, inWidth, inHeight,outWidth, outHeight);
final Bitmap downsampled =
downsampleWithSize(invalidatingStream, bufferedStream, options, pool,inWidth, inHeight, sampleSize,
decodeFormat);
final Exception streamException =exceptionStream.getException();
if (streamException != null) {
thrownew RuntimeException(streamException);
}
Bitmap rotated = null;
if (downsampled != null) {
rotated =TransformationUtils.rotateImageExif(downsampled, pool, orientation);
if (!downsampled.equals(rotated) &&!pool.put(downsampled)) {
downsampled.recycle();
}
}
return rotated;
} finally {
byteArrayPool.releaseBytes(bytesForOptions);
byteArrayPool.releaseBytes(bytesForStream);
exceptionStream.release();
releaseOptions(options);
}
}
private BitmapdownsampleWithSize(MarkEnforcingInputStream is,RecyclableBufferedInputStream bufferedStream,
BitmapFactory.Options options,BitmapPool pool, int inWidth, int inHeight, int sampleSize,
DecodeFormat decodeFormat) {
Bitmap.Config config = getConfig(is, decodeFormat);
options.inSampleSize = sampleSize;
options.inPreferredConfig = config;
if ((options.inSampleSize == 1 || Build.VERSION_CODES.KITKAT <=Build.VERSION.SDK_INT) && shouldUsePool(is)) {
int targetWidth = (int) Math.ceil(inWidth / (double) sampleSize);
int targetHeight = (int) Math.ceil(inHeight / (double) sampleSize);
setInBitmap(options,pool.getDirty(targetWidth, targetHeight, config));
}
return decodeStream(is, bufferedStream,options);
}
publicint[] getDimensions(MarkEnforcingInputStreamis, RecyclableBufferedInputStream bufferedStream,
BitmapFactory.Options options) {
options.inJustDecodeBounds = true;
decodeStream(is, bufferedStream, options);
options.inJustDecodeBounds = false;
returnnewint[] { options.outWidth, options.outHeight };
}
privatestatic BitmapdecodeStream(MarkEnforcingInputStream is, RecyclableBufferedInputStreambufferedStream,
BitmapFactory.Options options) {
if (options.inJustDecodeBounds) {
is.mark(MARK_POSITION);
} else {
bufferedStream.fixMarkLimit();
}
final Bitmap result =BitmapFactory.decodeStream(is, null, options);
try {
if (options.inJustDecodeBounds) {
is.reset();
}
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.ERROR)) {
Log.e(TAG, "Exception loadinginDecodeBounds=" +options.inJustDecodeBounds
+ " sample=" + options.inSampleSize, e);
}
}
return result;
}
...
}
BitmapResource
publicclassBitmapResourceimplementsResource<Bitmap> {
privatefinal Bitmap bitmap;
privatefinal BitmapPool bitmapPool;
/**
* Returns a new {@link BitmapResource} wrapping the given {@link Bitmap}if the Bitmap is non-null or null if the
* given Bitmap is null.
*
* @param bitmap A Bitmap.
* @param bitmapPool A non-null {@linkBitmapPool}.
*/
publicstatic BitmapResource obtain(Bitmap bitmap,BitmapPool bitmapPool) {
if (bitmap == null) {
returnnull;
} else {
returnnew BitmapResource(bitmap, bitmapPool);
}
}
public BitmapResource(Bitmap bitmap,BitmapPool bitmapPool) {
if (bitmap == null) {
thrownew NullPointerException("Bitmap must not be null");
}
if (bitmapPool == null) {
thrownew NullPointerException("BitmapPool must not be null");
}
this.bitmap = bitmap;
this.bitmapPool = bitmapPool;
}
@Override
public Bitmap get() {
return bitmap;
}
@Override
publicint getSize() {
return Util.getBitmapByteSize(bitmap);
}
@Override
publicvoid recycle() {
if (!bitmapPool.put(bitmap)) {
bitmap.recycle();
}
}
}
一层层继续向上返回,StreamBitmapDecoder会将值返回到ImageVideoBitmapDecoder当中,而ImageVideoBitmapDecoder又会将值返回到GifBitmapWrapperResourceDecoder的decodeBitmapWrapper()方法当中
decodeBitmapWrapper
private GifBitmapWrapperdecodeBitmapWrapper(ImageVideoWrapper toDecode, int width, int height) throws IOException {
GifBitmapWrapper result = null;
Resource<Bitmap> bitmapResource = bitmapDecoder.decode(toDecode,width, height);
if (bitmapResource != null) {
result = new GifBitmapWrapper(bitmapResource, null);//又把Resource<Bitmap>封装成GifBitmapWrapper
}
return result;
}
GifBitmapWrapper
publicclassGifBitmapWrapper {
privatefinal Resource<GifDrawable> gifResource;
privatefinal Resource<Bitmap> bitmapResource;
public GifBitmapWrapper(Resource<Bitmap>bitmapResource, Resource<GifDrawable> gifResource) {
if (bitmapResource != null && gifResource != null) {
thrownew IllegalArgumentException("Can only contain either a bitmapresource or a gif resource, not both");
}
if (bitmapResource == null && gifResource == null) {
thrownew IllegalArgumentException("Must contain either a bitmap resource or a gif resource");
}
this.bitmapResource = bitmapResource;
this.gifResource = gifResource;
}
/**
* Returns the size of the wrapped resource.
*/
publicint getSize() {
if (bitmapResource != null) {
return bitmapResource.getSize();
} else {
return gifResource.getSize();
}
}
/**
* Returns the wrapped {@link Bitmap} resource if it exists, or null.
*/
public Resource<Bitmap> getBitmapResource(){
return bitmapResource;
}
/**
* Returns the wrapped {@link GifDrawable} resource if it exists, ornull.
*/
public Resource<GifDrawable>getGifResource() {
return gifResource;
}
}
一直向上返回,返回到GifBitmapWrapperResourceDecoder最外层的decode()方法的时候,会对它再做一次封装
@Override
public Resource<GifBitmapWrapper>decode(ImageVideoWrapper source, int width, int height) throws IOException {
ByteArrayPool pool = ByteArrayPool.get();
byte[] tempBytes = pool.getBytes();
GifBitmapWrapper wrapper = null;
try {
wrapper = decode(source, width, height, tempBytes);
} finally {
pool.releaseBytes(tempBytes);
}
return wrapper != null ? new GifBitmapWrapperResource(wrapper) : null;//又封装成GifBitmapWrapperResource,最后返回的是Resource<GifBitmapWrapper>
}
GifBitmapWrapperResource
publicclassGifBitmapWrapperResourceimplementsResource<GifBitmapWrapper> {
privatefinal GifBitmapWrapper data;
publicGifBitmapWrapperResource(GifBitmapWrapper data) {
if (data == null) {
thrownew NullPointerException("Data must not be null");
}
this.data = data;
}
@Override
public GifBitmapWrapper get() {
return data;
}
@Override
publicint getSize() {
return data.getSize();
}
@Override
publicvoid recycle() {
Resource<Bitmap> bitmapResource = data.getBitmapResource();
if (bitmapResource != null) {
bitmapResource.recycle();
}
Resource<GifDrawable> gifDataResource = data.getGifResource();
if (gifDataResource != null) {
gifDataResource.recycle();
}
}
}
DecodeJob的decodeFromSourceData返回的是Resource<T>对象,也就是Resource<GifBitmapWrapper>对象,最终返回到decodeFromSource
public Resource<Z> decodeFromSource() throws Exception {
Resource<T> decoded = decodeSource();
return transformEncodeAndTranscode(decoded);
}
transformEncodeAndTranscode
private Resource<Z>transformEncodeAndTranscode(Resource<T> decoded) {
long startTime = LogTime.getLogTime();
Resource<T> transformed = transform(decoded);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Transformed resource from source", startTime);
}
writeTransformedToCache(transformed);
startTime = LogTime.getLogTime();
Resource<Z> result = transcode(transformed);//transcode方法把Resource<T>转换成Resource<Z>
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Transcoded transformed from source", startTime);
}
return result;
}
private Resource<Z>transcode(Resource<T> transformed) {
if (transformed == null) {
returnnull;
}
return transcoder.transcode(transformed);
}
load()方法返回的那个DrawableTypeRequest对象,它的构建函数中去构建了一个FixedLoadProvider对象,然后我们将三个参数传入到了FixedLoadProvider当中,其中就有一个GifBitmapWrapperDrawableTranscoder对象。后来在onSizeReady()方法中获取到了这个参数,并传递到了Engine当中,然后又由Engine传递到了DecodeJob当中。因此,这里的transcoder其实就是这个GifBitmapWrapperDrawableTranscoder对象,核心作用是用来转码的,都封装成Resource<GlideDrawable>
publicclassGifBitmapWrapperDrawableTranscoderimplementsResourceTranscoder<GifBitmapWrapper, GlideDrawable> {
privatefinal ResourceTranscoder<Bitmap,GlideBitmapDrawable> bitmapDrawableResourceTranscoder;
public GifBitmapWrapperDrawableTranscoder(
ResourceTranscoder<Bitmap,GlideBitmapDrawable> bitmapDrawableResourceTranscoder) {
this.bitmapDrawableResourceTranscoder =bitmapDrawableResourceTranscoder;
}
@Override
public Resource<GlideDrawable>transcode(Resource<GifBitmapWrapper> toTranscode) {
GifBitmapWrapper gifBitmap = toTranscode.get();
Resource<Bitmap> bitmapResource = gifBitmap.getBitmapResource();
final Resource<? extends GlideDrawable>result;
if (bitmapResource != null) {
result = bitmapDrawableResourceTranscoder.transcode(bitmapResource);
} else {
result =gifBitmap.getGifResource();
}
return (Resource<GlideDrawable>) result;
}
...
}
DecodeJob继续向上返回到EngineRunnable的decodeFromSource(),再回到decode,再回到run中
@Override
publicvoid run() {
if (isCancelled) {
return;
}
Exception exception = null;
Resource<?> resource = null;
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);//表示图片加载完成
}
}
privatevoid onLoadComplete(Resource resource) {
manager.onResourceReady(resource);
}
manager就是EngineJob,调用的是EngineJob的onResourceReady()方法
EngineJob
class EngineJob implementsEngineRunnable.EngineRunnableManager {
privatestaticfinal Handler MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper(), new MainThreadCallback());
privatefinal List<ResourceCallback> cbs = new ArrayList<ResourceCallback>();
...
publicvoid addCallback(ResourceCallback cb) {
Util.assertMainThread();
if (hasResource) {
cb.onResourceReady(engineResource);
} elseif (hasException) {
cb.onException(exception);
} else {
cbs.add(cb);
}
}
@Override
publicvoid onResourceReady(final Resource<?> resource) {
this.resource = resource;
MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();//发送完成的消息
}
privatevoid handleResultOnMainThread() {
if (isCancelled) {
resource.recycle();
return;
} elseif (cbs.isEmpty()) {
thrownew IllegalStateException("Received a resource without any callbacks to notify");
}
engineResource = engineResourceFactory.build(resource, isCacheable);
hasResource = true;
engineResource.acquire();
listener.onEngineJobComplete(key, engineResource);
for (ResourceCallback cb : cbs) {
if (!isInIgnoredCallbacks(cb)) {
engineResource.acquire();
cb.onResourceReady(engineResource);
}
}
engineResource.release();
}
@Override
publicvoid onException(final Exception e) {
this.exception = e;
MAIN_THREAD_HANDLER.obtainMessage(MSG_EXCEPTION, this).sendToTarget();
}
privatevoid handleExceptionOnMainThread() {
if (isCancelled) {
return;
} elseif (cbs.isEmpty()) {
thrownew 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);
}
}
}
privatestaticclassMainThreadCallbackimplementsHandler.Callback {
@Override
publicboolean handleMessage(Message message) {
if (MSG_COMPLETE == message.what || MSG_EXCEPTION ==message.what) {
EngineJob job =(EngineJob) message.obj;
if (MSG_COMPLETE == message.what) {
job.handleResultOnMainThread();//内部用循环调用了所有的调用了所有ResourceCallback的onResourceReady()方法
} else {
job.handleExceptionOnMainThread();
}
returntrue;
}
returnfalse;
}
}
...
}
addCallback增加了ResourceCallback,addCallback的调用处
publicclassEngineimplementsEngineJobListener,
MemoryCache.ResourceRemovedListener,
EngineResource.ResourceListener {
...
public <T, Z, R> LoadStatus load(Keysignature, int width, int height, DataFetcher<T> fetcher,
DataLoadProvider<T, Z>loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z,R> transcoder, Priority priority,
boolean isMemoryCacheable, DiskCacheStrategydiskCacheStrategy, ResourceCallback cb) {
...
EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);
DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width,height, fetcher, loadProvider, transformation,
transcoder, diskCacheProvider,diskCacheStrategy, priority);
EngineRunnable runnable = newEngineRunnable(engineJob, decodeJob, priority);
jobs.put(key, engineJob);
engineJob.addCallback(cb);//这里添加call back
engineJob.start(runnable);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Started new load", startTime, key);
}
returnnew LoadStatus(cb, engineJob);
}
...
}
追溯一下ResourceCallback,在GenericRequest的onSizeReady()中
publicfinalclassGenericRequest<A, T, Z, R> implementsRequest, SizeReadyCallback,
ResourceCallback {
...
@Override
publicvoid onSizeReady(int width, int height) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
if (status != Status.WAITING_FOR_SIZE) {
return;
}
status = Status.RUNNING;
width = Math.round(sizeMultiplier * width);
height = Math.round(sizeMultiplier * height);
ModelLoader<A, T> modelLoader = loadProvider.getModelLoader();
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;
loadStatus = engine.load(signature, width, height, dataFetcher,loadProvider, transformation,
transcoder, priority,isMemoryCacheable, diskCacheStrategy, this);//发现传入的就是this,所以传入的就是GenericRequest本身
loadedFromMemoryCache = resource != null;
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
}
...
}
EngineJob的回调最终其实就是回调到了GenericRequest的onResourceReady()方法当中
publicvoid onResourceReady(Resource<?> resource) {
if (resource == null) {
onException(new Exception("Expected to receive aResource<R> with an object of " + transcodeClass
+ " inside, but instead got null."));
return;
}
Object received = resource.get();//获取了封装的图片对象,传入了另一个onResourceReady中
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 nullResource object, "
+ "rather than a Resource objectcontaining null data.")
));
return;
}
if (!canSetResource()) {
releaseResource(resource);
// We can't setthe status to complete before asking canSetResource().
status = Status.COMPLETE;
return;
}
onResourceReady(resource, (R) received);
}
privatevoid onResourceReady(Resource<?> resource, R result) {
// We must callisFirstReadyResource 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);
//那么这个target又是什么呢?这个又需要向上翻很久了,在第三步into()方法的一开始,我们就分析了在into()方法的最后一行,调用了glide.buildImageViewTarget()方法来构建出一个Target,而这个Target就是一个GlideDrawableImageViewTarget对象
}
notifyLoadSuccess();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("Resourceready in " +LogTime.getElapsedMillis(startTime) + " size: "
+ (resource.getSize() *TO_MEGABYTE) + "fromCache: " +loadedFromMemoryCache);
}
}
GlideDrawableImageViewTarget
publicclassGlideDrawableImageViewTargetextendsImageViewTarget<GlideDrawable>{
privatestaticfinalfloat SQUARE_RATIO_MARGIN = 0.05f;
privateint maxLoopCount;
private GlideDrawable resource;
public GlideDrawableImageViewTarget(ImageViewview) {
this(view, GlideDrawable.LOOP_FOREVER);
}
public GlideDrawableImageViewTarget(ImageViewview, int maxLoopCount) {
super(view);
this.maxLoopCount = maxLoopCount;
}
@Override
publicvoid 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();
}
@Override
protectedvoid setResource(GlideDrawable resource) {
view.setImageDrawable(resource);
}
@Override
publicvoid onStart() {
if (resource != null) {
resource.start();
}
}
@Override
publicvoid onStop() {
if (resource != null) {
resource.stop();
}
}
}
父类
publicabstractclassImageViewTarget<Z> extendsViewTarget<ImageView, Z> implementsGlideAnimation.ViewAdapter {
...
@Override
publicvoid onResourceReady(Z resource,GlideAnimation<? super Z> glideAnimation) {
if (glideAnimation == null || !glideAnimation.animate(resource, this)) {
setResource(resource);//这里需要交给子类去实现
}
}
protectedabstractvoid setResource(Z resource);
}
子类的setResource实现:GlideDrawableImageViewTarget的setResource()
@Override
protectedvoid setResource(GlideDrawable resource) {
view.setImageDrawable(resource);
}
他的源码太难了,有机会画个流程图压压惊