Glide源码初探

借鉴自郭霖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(用于加载图片)对象,传入不同类型的参数会得到不同类型的ModelLoaderURL代表传入的是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中得到的FixedLoadProvidergetSourceDecoder得到的是一个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();

       }

   }

}

 

DecodeJobdecodeFromSourceData返回的是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继续向上返回到EngineRunnabledecodeFromSource(),再回到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();//内部用循环调用了所有的调用了所有ResourceCallbackonResourceReady()方法

                } else {

                    job.handleExceptionOnMainThread();

                }

                returntrue;

            }

            returnfalse;

       }

   }

 

   ...

}

 

addCallback增加了ResourceCallbackaddCallback的调用处

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,在GenericRequestonSizeReady()

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的回调最终其实就是回调到了GenericRequestonResourceReady()方法当中

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实现:GlideDrawableImageViewTargetsetResource()

@Override

   protectedvoid setResource(GlideDrawable resource) {

       view.setImageDrawable(resource);

}

 

他的源码太难了,有机会画个流程图压压惊

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值