美文网首页
(拾起.笔记)源码分析记录之Glide源码分析(一)

(拾起.笔记)源码分析记录之Glide源码分析(一)

作者: 其实小吴人挺好 | 来源:发表于2018-06-14 17:53 被阅读0次

    写在前面

    这篇文章是个人参考源码及博客编写的笔记,主要是对源码简单分析。都是个人对源码的见解记录下来,只是介绍流程,供个人参考,如有需要阅读的,建议对源码和本文进行对照分析或者打开两个界面,以免翻车。文章有点长。

    开始:

    分析Glide版本:compile 'com.github.bumptech.glide:glide:3.7.0'
    查看源码时请对应版本,以免混乱

    Glide.with(context).load(url).into(imageView);

    上面就是Glide API调用最基本的的流程

    点进去Glide 就会看到with方法中会有四个方法,其中的参数又Activity 、context 、fragmentActivity、application

    Q1

    这里使用的是Activity为参数传递进去

    public static RequestManager with(Activity activity) {
    
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
    
        return retriever.get(activity);
    
    }
    

    在with方法中可以接收五种不同的参数,看下图


    444.png

    这里只需要对参数为activity情况下进行分析,
    RequestManagerRetriever.get() 获取一个RequestManagerRetriever 对象之后,调用get(activity)方法,然后将RequestManagerRetriever

    Q2 get(Activity)。

    public RequestManager get(Activity activity) {
    
        //判断是否是后台线程,也就是是否在UI线程
    
        if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
            return get(activity.getApplicationContext());
        } else {
            assertNotDestroyed(activity);
            android.app.FragmentManager fm = activity.getFragmentManager();
            return fragmentGet(activity, fm);
    
        }
    
    }
    

    前面的判断是在判断是否是后台线程,否则为UI线程,如果后台线程,就传入一个application上下文,然后进入到else方法中。先确保它还没销毁(assertNotDestroyed),再调用activity.getFragmentManager()通过activity获取一个Fragment的管理器,然后做为参数传入到fragmentGet(activity, fm) 方法中。

    Q3

    @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 = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
    
            current.setRequestManager(requestManager);
    
        }
    
        return requestManager;
    
    }
    

    RequestManagerFragment 是继承于fragment,也就是说RequestManagerFragment 其实就是一个

    fragment,自定义该类的其实就是在里面创建一个ActivityFragmentLifecycle,并将它的生命周期和

    fragment相关联起来;

    getRequestManagerFragment(fm)就是创建一个RequestManagerFragment

    Q4

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) {
    
        RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    
        if (current == null) {
    
            current = pendingRequestManagerFragments.get(fm);
    
            if (current == null) {
    
                current = new RequestManagerFragment();
    
                pendingRequestManagerFragments.put(fm, current);
    
                fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
    
                handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
    
            }
    
        }
    
        return current;
    
    }
    

    在创建RequestManagerFragment 的时候,它是通过findFragmentByTag来获取,如果没有就又从

    保存的队列里面获取,再没有就new出一个,然后保存入Map中,在添加到FragmentManager中,然后发送一条handle消息,再将RequestManagerFragment返回

    我们回到Q3中

    在getRequestManagerFragment的时候,如果不是new出来一个新的RequestManager 就不会为空,否则它也会去创建一个RequestManager 并将生命周期的监听和树节点,并将RequestManager 设置到getRequestManagerFragment中去再将RequestManager

    这里with的一系列源码已经解析完成了。其主要的目的就是创建一个fragment并且监听绑定它的生命周期变换,以免在glide在图片请求的时候,做一系列的停止等操作。

    with方法就是通过监听fragment生命周期对图片进行操作,比如说暂停加载等

    接下来就load()

    因为with的时候返回的是RequestManager ,所以load就是RequestManager 的方法

    在Request有多个load方法

    111.png

    其中包括byte数组、file、uri等等,说明Glide 可以接收多种类型的请求,这里我们对load(String)进行分析

    Q5

    public DrawableTypeRequest<String> load(String string) {
    
        return (DrawableTypeRequest<String>) fromString().load(string);
    
    }
    

    这个方法会返回一个DrawableTypeRequest类型,并指定它的泛型是String,然后调用

    fromString() 再调用load(String)

    进去看看fromString

    Q6

    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);
    
        ....
    
        return optionsApplier.apply(new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,glide, requestTracker, lifecycle, optionsApplier));
    
    }
    

    这个方法很短,调用Glide.buildStreamModelLoader(modelClass, context) 和 Glide.buildFileDescriptorModelLoader(modelClass, context)都返回一个ModelLoader对象。这里我们只要知道 ModelLoader 接口是加载图片的就好,因为里面过于复杂,不做过多介绍。他会根据你传入的参数类型返回相应的对象,我们在fromString方法传入的是String.class,所以这里会返回StreamStringLoader。最后一行会new 一个 DrawableTypeRequest 将 modelClass,StreamStringLoader等参数传进去,并将其返回。

    Q7

    222.png

    进入到该类,其他的我们先不要注意,你会发现该类中有asGif(),asBitmap(),这个就是我们在强制指定加载静态图片和动态图片,看看它的方法

    Q8

    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(),默认的会使用DrawableTypeRequest,使用fromString()就返回一个DrawableTypeRequest,再来Q5 中的load(Stirng),点进去直接跳到DrawableTypeRequest的父类DrawableRequestBuilder。

    Q9

    @Override
    
    public DrawableRequestBuilder<ModelType> load(ModelType model) {
    
        super.load(model);
    
        return this;
    
    }
    
    public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> load(ModelType model) {
    
        this.model = model;
    
        isModelSet = true;
    
        return this;
    
    }
    

    只是简单的赋值并返回this,看看它的全部方法

    333.png

    回发现,我们在调用api的时候,使用的方法大都在这个类中。致此load已经分析好了

    看一下into,这个方法较为复杂,这里只分析主线,对于分岔路可以自行去分析。

    在load分析的DrawableRequestBuilder类方法的截图中,你会看到一个into(),这个就是into的入口

    进去看看:

    Q10

    public Target<TranscodeType> into(ImageView view) {
    
        Util.assertMainThread();
    
        if (view == null) {
    
            throw new IllegalArgumentException("You must pass in a non null View");
    
        }
    
        if (!isTransformationSet && view.getScaleType() != null) {
    
            switch (view.getScaleType()) {
    
                case CENTER_CROP:
    
                applyCenterCrop();
    
            break;
    
            case FIT_CENTER:
    
            case FIT_START:
    
            case FIT_END:
    
                applyFitCenter();
    
                break;
    
                //$CASES-OMITTED$
    
            default:
    
                // Do nothing.
    
            }
    
        }
    
        return into(glide.buildImageViewTarget(view, transcodeClass));
    }
    

    前面一些代码先不用管,我们先注意一下最后一行代码,into(glide.buildImageViewTarget(view, transcodeClass)); 在into当中调用glide.buildImageViewTarget(view, transcodeClass),老规矩,进去看看

    Q11

    <R> Target<R> buildImageViewTarget(ImageView imageView, Class<R> transcodedClass) {
    
        return imageViewTargetFactory.buildTarget(imageView, transcodedClass);
    
    }
    

    紧接的是调用一个buildTarget

    Q12

    public <Z> Target<Z> buildTarget(ImageView view, Class<Z> clazz) {
    
        if (GlideDrawable.class.isAssignableFrom(clazz)) {
    
            return (Target<Z>) new GlideDrawableImageViewTarget(view);
    
        } else if (Bitmap.class.equals(clazz)) {
    
            return (Target<Z>) new BitmapImageViewTarget(view);
    
        } else if (Drawable.class.isAssignableFrom(clazz)) {
    
            return (Target<Z>) new DrawableImageViewTarget(view);
    
        } else {
    
            throw new IllegalArgumentException("Unhandled class: " + clazz
    
            + ", try .as*(Class).transcode(ResourceTranscoder)");
    
        }
    
    }
    

    这里会根据class来判断要创建哪个对象,这里我们只需要知道会返回一个 GlideDrawableImageViewTarget对象,因为如果要分析其class的话,还要需要很大的功夫,这里我们只关心主线,返回GlideDrawableImageViewTarget,我们回到Q10中的最后一行代码,into(GlideDrawableImageViewTarget),

    Q13

    public <Y extends Target<TranscodeType>> Y into(Y target) {
    
        Util.assertMainThread();
    
        if (target == null) {
    
            throw new IllegalArgumentException("You must pass in a non null Target");
    
        }
    
        if (!isModelSet) {
    
            throw new IllegalArgumentException("You must first set a model (try #load())");
    
        }
    
        Request previous = target.getRequest();
    
        if (previous != null) {
    
            previous.clear();
    
            requestTracker.removeRequest(previous);
    
            previous.recycle();
    
        }
    
        Request request = buildRequest(target);
    
        target.setRequest(request);
    
        lifecycle.addListener(target);
    
        requestTracker.runRequest(request);
    
        return target;
    
    }
    

    其中target.getRequest()是获取当前的taget是否有请求,如果存在就将它清空回收,然后在重新创建一个Request请求对象,也就是调用huildRequest(target),

    我们看看 buildRequest(target)方法,会返回一个Request类型,

    Q14

    private Request buildRequest(Target<TranscodeType> target) {
    
        if (priority == null) {
    
            priority = Priority.NORMAL;
    
        }
    
        return buildRequestRecursive(target, null);
    
    }
    

    再调用buildRequestRecursive 把 GlideDrawableImageViewTarget 和 null 丢进去

    Q15

    private Request buildRequestRecursive(Target<TranscodeType> target, ThumbnailRequestCoordinator parentCoordinator) {
    
        .....
    
        } else {
    
            // Base case: no thumbnail.
    
            return obtainRequest(target, sizeMultiplier, priority, parentCoordinator);
    
        }
    
    }
    

    主要看最后一行 obtainRequest(target, sizeMultiplier, priority, parentCoordinator);

    Q16

    private Request obtainRequest(Target<TranscodeType> target, float sizeMultiplier, Priority priority,RequestCoordinator requestCoordinator) {
    
        return GenericRequest.obtain(
    
        loadProvider,
    
        model,
    
        signature,
    
        context,
    
        priority,
    
        target,
    
        sizeMultiplier,
    
        placeholderDrawable,
    
        placeholderId,
    
        errorPlaceholder,
    
        errorId,
    
        fallbackDrawable,
    
        fallbackResource,
    
        requestListener,
    
        requestCoordinator,
    
        glide.getEngine(),
    
        transformation,
    
        transcodeClass,
    
        isCacheable,
    
        animationFactory,
    
        overrideWidth,
    
        overrideHeight,
    
        diskCacheStrategy);
    
    }
    

    紧接的会将一些乱七八糟的参数传入到 GenericRequest.obtain(..)方法中

    Q17

    public static <A, T, Z, R> GenericRequest<A, T, Z, R> obtain(....) {
    
        @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;
    
    }
    

    这里会调用request = new GenericRequest<A, T, Z, R>() 创建出一个GenericRequest对象,并将这些乱七八糟的参数传进来,并返回GenericRequest,其中很多的参数我们都是比较熟悉的,像什么placeholderId、errorPlaceholder、diskCacheStrategy等等,这里可以看出,刚才在GenericRequestBuilder中设置的参数都会封装到此处来,也就是Glide的API,所以在Q13中的buildRequest(target); 返回来的Request对象,其实就是GenericRequest,GenericRequest里面封装这api中的属性值。

    接下来我们回到Q13中,看看这个方法 requestTracker.runRequest(request) ,调用runRequest将GenericRequest传递过去,来看看runRequest方法

    Q18

    public void runRequest(Request request) {
    
        requests.add(request);
    
        if (!isPaused) {
    
            request.begin();
    
        } else {
    
            pendingRequests.add(request);
    
        }
    
    }
    

    这里判断Glide状态是否为停止的状态,然后调用GenericRequest的begin() 方法,否则将Request添加到待执行队列,所以我们进去看看GenericRequest的begin方法

    Q19

    @Override
    
    public void begin() {
    
        startTime = LogTime.getLogTime();
    
        if (model == null) {
    
            onException(null);
    
            return;
    
        }
    
        status = Status.WAITING_FOR_SIZE;
    
        if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
    
            onSizeReady(overrideWidth, overrideHeight);
    
        } else {
    
            target.getSize(this);
    
        }
    
        if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
    
            target.onLoadStarted(getPlaceholderDrawable());
    
        }
    
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
    
            logV("finished run method in " + LogTime.getElapsedMillis(startTime));
    
        }
    
    }
    

    我们先看看onException(null) ,先判断model是否为空,mode就是在Q9 中 load传过来的String,也就是uri,也就是说uri为空的时候,就会调用onException方法,进去看看

    Q20

    @Override
    
    public void onException(Exception e) {
    
        if (Log.isLoggable(TAG, Log.DEBUG)) {
    
            Log.d(TAG, "load failed", e);
    
        }
    
        status = Status.FAILED;
    
        //TODO: what if this is a thumbnail request?
    
        if (requestListener == null || !requestListener.onException(e, model, target, isFirstReadyResource())) {
    
            setErrorPlaceholder(e);
    
        }
    
    }
    

    经过一系列的判断后,会调用setErrorPlaceholder(e),看名字就知道,他就是用来设置占位符的,也就是错误图片

    Q21

    private void setErrorPlaceholder(Exception e) {
    
        if (!canNotifyStatusChanged()) {
    
            return;
    
        }
    
        Drawable error = model == null ? getFallbackDrawable() : null;
    
        if (error == null) {
    
            error = getErrorDrawable();
    
        }
    
        if (error == null) {
    
            error = getPlaceholderDrawable();
    
        }
    
        target.onLoadFailed(e, error);
    
    }
    

    这里判断error是否为空之后,就会获取一个error图片,还是没有的话再获取一个placeholder图片

    然后调用target.onLoadFailed(e, error) 这个tagat就是Q11 和Q12中的GlideDrawableImageViewTarget ,进去之后onLoadFailed()是在它父类ImageViewTarget中

    Q22

    @Override
    public void onLoadFailed(Exception e, Drawable errorDrawable) {
    
        view.setImageDrawable(errorDrawable);
    
    }
    

    只是将Drawable 设置进ImageView中去。onExption()方法就是这样,所以我们接下来回到Q19 对下面就行分析,

    Q23

    @Override
    public void begin() {
    
        startTime = LogTime.getLogTime();
    
        if (model == null) {
    
            onException(null);
    
            return;
    
        }
    
        status = Status.WAITING_FOR_SIZE;
    
        if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
    
            onSizeReady(overrideWidth, overrideHeight);
    
        } else {
    
            target.getSize(this);
    
        }
    
        if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
    
            target.onLoadStarted(getPlaceholderDrawable());
    
        }
    
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
    
            logV("finished run method in " + LogTime.getElapsedMillis(startTime));
    
        }
    
    }
    

    这里会调用到onSizeReady() 方法,这个宽高是自定义的宽高,是通过一系列的运算之后得到的宽高,点击进去看看这个方法,

    Q24

    @Override
    public void 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);
    
        loadedFromMemoryCache = resource != null;
    
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
    
            logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
    
        }
    
    }
    

    这时会看到一个loadProvider.getModeLoader()方法,在同getModeLoader之后获取到一个ModeLoader对象在调用它的getResource(model,width,height);方法获取到一个DataFetcher对象,这里先去了解一下loadProvider.getModeLoader()的方法,这个loadProvider其实就是分析load()方法的时候进行初始化的,我们回到在Q6 中在loadGeneric的时候,会创建出一个DrawableTypeRequest,在构造方法的时候,会调用super方法,super方法的第三个参数当中需要传入一个LoadProvider 对象,然后就会调用buildProvider加载出一个LoadProvider对象,想看看这个类

    Q25

    public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<ModelType> implements DownloadOptions {
    
    private final ModelLoader<ModelType, InputStream> streamModelLoader;
    
    private final ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader;
    
    private final RequestManager.OptionsApplier optionsApplier;
    
    private static <A, Z, R> FixedLoadProvider<A, ImageVideoWrapper, Z, R> buildProvider(Glide glide,
    
    ModelLoader<A, InputStream> streamModelLoader,
    
        ModelLoader<A, ParcelFileDescriptor> fileDescriptorModelLoader, Class<Z> resourceClass,Class<R> transcodedClass,ResourceTranscoder<Z, R> transcoder) {
    
            if (streamModelLoader == null && fileDescriptorModelLoader == null) {
    
                return null;
    
            }
    
        if (transcoder == null) {
    
            transcoder = glide.buildTranscoder(resourceClass, transcodedClass);
    
        }
    
        DataLoadProvider<ImageVideoWrapper, Z> dataLoadProvider = glide.buildDataProvider(ImageVideoWrapper.class,resourceClass);
    
        ImageVideoModelLoader<A> modelLoader = new ImageVideoModelLoader<A>(streamModelLoader,fileDescriptorModelLoader);
    
            return new FixedLoadProvider<A, ImageVideoWrapper, Z, R>(modelLoader, transcoder, dataLoadProvider);
    
    }
    
        DrawableTypeRequest(Class<ModelType> modelClass, ModelLoader<ModelType, InputStream> streamModelLoader,ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader, Context context, Glide glide,RequestTracker requestTracker, Lifecycle lifecycle, RequestManager.OptionsApplier optionsApplier) {
    
            super(context, modelClass,
    
            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));
        }
    
    }
    

    先看看 transcoder = glide.buildTranscoder(resourceClass, transcodedClass),这里你只要知道会返回一个ResourceTranscoder的子类GifBitmapWrapperDrawableTranscoder对象,它是用于对图片进行转码,紧接的就是glide.buildDataProvider(ImageVideoWrapper.class, resourceClass) 构建一个DataLoadProvider,这里你也需要只知道它是创建一个ImageVideoGifDrawableLoadProvider

    对象,再接的就是new ImageVideoModelLoader 将在Q6 中构建的ModelLoade封装进去,最后就是通过 new FixedLoadProvider<A, ImageVideoWrapper, Z, R>(modelLoader, transcoder, dataLoadProvider); 将ImageVideoModelLoader,GifBitmapWrapperDrawableTranscoder,ImageVideoGifDrawableLoadProvider封装进去,所以在Q24中的loadProvider其实就是FixedLoadProvider,也就是说loadProvider.getModelLoader()获取的就是封装进去的ImageVideoModelLoader,接下来回到Q24中,会通过ImagVideoModelLoader对象调用这个modelLoader.getResourceFetcher(model, width, height)方法获取到一个DataFetcher对象,进去看看ImagVideoModelLoader这个类

    Q26

    public class ImageVideoModelLoader<A> implements ModelLoader<A, ImageVideoWrapper> {
    
        private static final String TAG = "IVML";
    
        private final ModelLoader<A, InputStream> streamLoader;
    
        private final ModelLoader<A, ParcelFileDescriptor> fileDescriptorLoader;
    
        public ImageVideoModelLoader(ModelLoader<A, InputStream> streamLoader,
    
        ModelLoader<A, ParcelFileDescriptor> fileDescriptorLoader) {
    
            if (streamLoader == null && fileDescriptorLoader == null) {
    
                throw new NullPointerException("At least one of streamLoader and fileDescriptorLoader must be non null");
    
            }
    
            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) {
    
                return new ImageVideoFetcher(streamFetcher, fileDescriptorFetcher);
    
            } else {
    
                return null;
    
            }
    
        }
    
        static class ImageVideoFetcher implements DataFetcher<ImageVideoWrapper> {
    
            private final DataFetcher<InputStream> streamFetcher;
    
            private final DataFetcher<ParcelFileDescriptor> fileDescriptorFetcher;
    
            public ImageVideoFetcher(DataFetcher<InputStream> streamFetcher,
    
            DataFetcher<ParcelFileDescriptor> fileDescriptorFetcher) {
    
                this.streamFetcher = streamFetcher;
    
                this.fileDescriptorFetcher = fileDescriptorFetcher;
    
            }
        }
    
    
        @SuppressWarnings("resource")
    
        // @see ModelLoader.loadData
    
        @Override
    
        public ImageVideoWrapper loadData(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 fetching ParcelFileDescriptor", e);
    
                    }
    
                    if (is == null) {
    
                        throw e;
    
                    }
    
                }
    
            }
    
            return new ImageVideoWrapper(is, fileDescriptor);
    
        }
    
    }
    

    看看getResourceFetcher方法中,获取一个streamFetcher ,streamLoader就是我们在loadGeneric()方法中创建的StreamStringLoader,调用他的getResourceFetcher就是得到一个HttpUrlFetcher,后面就是new ImageVideoFetcher 将HttpUrlFetcher和StreamStringLoader传进去,所以,我们在Q24得到的DataFetcher其实就是这个ImageVideoFetcher ,回到Q24中,接下来就是调用 engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,priority, isMemoryCacheable, diskCacheStrategy, this) 其中dataFetcher

    就是我们的ImageVideoFetcher,loadProvider就是 Q24中的FixedLoadProvider,transcoder就是FixedLoadProvider中的GifBitmapWrapperDrawableTranscoder,其中还包括是否开启内存缓存,硬盘缓存策略,还有一个this,这个this就是ResourceCallback接口,这个接口GenericRequest已经实现,然后就是engine中的load方法,

    Q26.1

    public <T, Z, R> LoadStatus load(....) {
    
    .....
    
        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 = new EngineRunnable(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);
    
        }
    
        return new LoadStatus(cb, engineJob);
    
    }
    

    看到一个engineJobFactory.build(...)其实就是创建一个EngineJob 对象,它是用来开启线程的,为后面的异步加载图片做准备。然后就是DecodeJob对象,是用来给是图片进行解码的。

    还有一个EngineRunnable,看名字就知道的,它是一个Runnable的子类,任何将DecodeJob,EngineJob 传进去,所以看看它的run方法,

    Q27

    @Override
    
    public void 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);
    
        }
    
    }
    

    这个run方法一旦运行,就说明它是在子线程中运行了,其中里面包括一个decode()方法

    Q28

    private Resource<?> decode() throws Exception {
    
        if (isDecodingFromCache()) {
    
            return decodeFromCache();
    
        } else {
    
            return decodeFromSource();
    
        }
    
    }
    

    这里会判断它是否是从缓存中去解码图片就会调用decodeFromCache,否则就调用decodeFromSource,我们先看看decodeFromSource方法,

    Q29

    private Resource<?> decodeFromSource() throws Exception {
    
        return decodeJob.decodeFromSource();
    
    }
    

    接着他会调用DecodeJob对象中的decodeFromSource方法,

    Q30

    public Resource<Z> decodeFromSource() throws Exception {
    
        Resource<T> decoded = decodeSource();
    
        return transformEncodeAndTranscode(decoded);
    
    }
    

    接着就是再调用decodeSource() 获取一个Resource对象,再调用transformEncodeAndTranscode()将Resource对象传进去处理,再返回一个Resource对象。先进入到decodeSource中,

    Q31

    private Resource<T> decodeSource() throws Exception {
    
        Resource<T> decoded = null;
    
        try {
    
            long startTime = LogTime.getLogTime();
    
            final A data = fetcher.loadData(priority);
    
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
    
                logWithTimeAndKey("Fetched data", startTime);
    
            }
    
            if (isCancelled) {
    
                return null;
    
            }
    
            decoded = decodeFromSourceData(data);
    
        } finally {
    
            fetcher.cleanup();
    
        }
    
        return decoded;
    
    }
    

    注意到一个方法,fetcher.loadData(priority),返回一个A,这个fercher就是在Q24、25、26中通过

    ImagVideoModelLoader得到一个ImageVideoFetcher对象,再来调用他的loadData方法,所以进去瞧一瞧

    Q32

    @Override
    
    public ImageVideoWrapper loadData(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 fetching ParcelFileDescriptor", e);
    
                }
    
                if (is == null) {
    
                    throw e;
    
                }
    
            }
    
        }
    
        return new ImageVideoWrapper(is, fileDescriptor);
    
    }
    

    就在这里,InputStream is = streamFetcher.loadData(priority); 这货返回一个InputStream 对象,也就是说streamFetcher.loadData(priority)就是请求数据返回来的图片流,这个streamFetcher就是在Q26 中new ImageVideoFetcher时传的HttpUrlFetcher和StreamStringLoader中的HttpUrlFetcher,所以这个streamFetcher.loadData(priority)就是调用HttpUrlFetcher中的loadData方法,看看呗

    Q33

    @Override
    public InputStream loadData(Priority priority) throws Exception {
    
        return loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/, glideUrl.getHeaders());
    
    }
    
    private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl, Map<String, String> headers)throws IOException {
    
        if (redirects >= MAXIMUM_REDIRECTS) {
    
            throw new IOException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
    
        } else {
    
            // Comparing the URLs using .equals performs additional network I/O and is generally broken.
    
            // See http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html.
    
            try {
    
                if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
    
                    throw new IOException("In re-direct loop");
    
                }
    
            } catch (URISyntaxException e) {
    
                // Do nothing, this is best effort.
    
            }
    
        }
    
        urlConnection = connectionFactory.build(url);
    
            for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
    
            urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
    
            }
    
        urlConnection.setConnectTimeout(2500);
    
        urlConnection.setReadTimeout(2500);
    
        urlConnection.setUseCaches(false);
    
        urlConnection.setDoInput(true);
    
        // Connect explicitly to avoid errors in decoders if connection fails.
    
        urlConnection.connect();
    
        if (isCancelled) {
    
            return null;
    
        }
    
        final int statusCode = urlConnection.getResponseCode();
    
        if (statusCode / 100 == 2) {
    
            return getStreamForSuccessfulRequest(urlConnection);
    
        } else if (statusCode / 100 == 3) {
    
            String redirectUrlString = urlConnection.getHeaderField("Location");
    
            if (TextUtils.isEmpty(redirectUrlString)) {
    
                throw new IOException("Received empty or null redirect url");
    
            }
    
            URL redirectUrl = new URL(url, redirectUrlString);
    
            return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
    
        } else {
    
            if (statusCode == -1) {
    
                throw new IOException("Unable to retrieve response code from HttpUrlConnection.");
    
            }
    
            throw new IOException("Request failed " + statusCode + ": " + urlConnection.getResponseMessage());
    
        }
    
    }
    

    这些就是网络请求,返回一个InputStream 对象,回到Q32中,最后一行的new ImageVideoWrapper(is, fileDescriptor),返回一个ImageVideoWrapper对象,然后将InputStream 封装进去,所以在Q31中的A 类型就是ImageVideoWrapper对象,Q31 DecodeJob.decodeSource中的final A data = fetcher.loadData(priority)分析完了,在回头看看Q31中,看这一行,decoded = decodeFromSourceData(data),将ImageVideoWrapper对象传进去

    Q34

    private Resource<T> decodeFromSourceData(A data) throws IOException {
    
        final Resource<T> decoded;
    
        if (diskCacheStrategy.cacheSource()) {
    
            decoded = cacheAndDecodeSourceData(data);
    
        } else {
    
            long startTime = LogTime.getLogTime();
    
            decoded = loadProvider.getSourceDecoder().decode(data, width, height);
    
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
    
                logWithTimeAndKey("Decoded from source", startTime);
    
            }
    
        }
    
        return decoded;
    
    }
    

    注意这个 decoded = loadProvider.getSourceDecoder().decode(data, width, height);这个方法,loadProvider就是FixedLoadProvider,在Q25中有解释,调用他的getSourceDecoder()获取到他在构造的时候传进去的ImageVideoGifDrawableLoadProvider对象,在调用它在构造方法中创建的GifBitmapWrapperResourceDecoder对象,再调用GifBitmapWrapperResourceDecoder的decode方法,

    Q35

    @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;
    
    }
    

    再调用它的decode重载方法

    Q36

    private GifBitmapWrapper decode(ImageVideoWrapper source, int width, int height, byte[] bytes) throws IOException {
    
        final GifBitmapWrapper result;
    
        if (source.getStream() != null) {
    
            result = decodeStream(source, width, height, bytes);
    
        } else {
    
            result = decodeBitmapWrapper(source, width, height);
    
        }
    
        return result;
    
    }
    

    判断source是否为空,sourcek就是ImageVideoWrapper,也就是刚才的A类型,传入到decodeFromSourceData(data)方法,而这个ImageVideoWrapper是持有InputStream对象的,是有这里不等于空,则调用decodeStream,

    Q37

    private GifBitmapWrapper decodeStream(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 gif may fail even if the type matches.
    
        if (result == null) {
    
            // We can only reset the buffered InputStream, so to start from the beginning of the stream, we need to
    
            // pass in a new source containing the buffered stream rather than the original stream.
    
            ImageVideoWrapper forBitmapDecoder = new ImageVideoWrapper(bis, source.getFileDescriptor());
    
            result = decodeBitmapWrapper(forBitmapDecoder, width, height);
    
        }
    
        return result;
    
    }
    

    这里先判断是否为GIF,是就调用decodeGifWrapper(bis, width, height),否则会创建一个ImageVideoWrapper 对象,调用decodeBitmapWrapper(forBitmapDecoder, width, height)传进去,所以加载普通图片就先进入到decodeBitmapWrapper方法中

    Q38

    private GifBitmapWrapper decodeBitmapWrapper(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);
    
        }
    
        return result;
    
    }
    

    通过调用 bitmapDecoder.decode(toDecode, width, height) 返回一个Resource对象,再将它封装到GifBitmapWrapper中,这个ditmapDecoder我们只要知道是一个 ImageVideoBitmapDecoder对象,我们只要往主线走,我们看一下他的方法,

    Q39

    @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);
    
            } 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;
    
    }
    

    在获取到ImageVideoWrapper 中的InputStream,之后再调用streamDecoder.decode(is, width, height);获取一个Resource<Bitmap> 泛型为Bitmap,这个streamDecoder只需要知道他是StreamBitmapDecoder对象,再来看看他的decode方法,

    Q40

    @Override
    public Resource<Bitmap> decode(InputStream source, int width, int height) {
    
        Bitmap bitmap = downsampler.decode(source, bitmapPool, width, height, decodeFormat);
    
        return BitmapResource.obtain(bitmap, bitmapPool);
    
    }
    

    然后。。它又去调用 downsampler.decode(source, bitmapPool, width, height, decodeFormat) 返回一个Bitmap对象,再封装到Resource中,downsampler就是Downsampler,里面主要是将InputStream 处理得到一个Bitmap对象,再是用BitmapResource将其封装,

    Q41

    public static BitmapResource obtain(Bitmap bitmap, BitmapPool bitmapPool) {
        if(bitmap == null) { 
            return null;
        }else{
            return new BitmapResource(bitmap, bitmapPool);
        }
     }
    

    是的,就是new 一个BitmapResource,所以得出,在Q38中streamDecoder.decode(is, width, height)方法中获取的就是一个BitmapResourced对象,然后在将BitmapResource对象封装到GifBitmapWrapper方法中,然后返回一步一步向上返回GifBitmapWrapper,Q38 到 Q37 到Q36 到Q35 ,那回到 Q35

    @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对GifBitmapWrapper进行封装,然后将GifBitmapWrapperResource返回到Q34 ,GifBitmapWrapperResource是继承自Resource,所以将这个GifBitmapWrapperResource返回到Q34,再到Q31,然后在到Q30

    到Q30 看看,我们刚刚就是分析的decodeSource,返回一个GifBitmapWrapperResource(wrapper) ,将GifBitmapWrapperResource 传入到transformEncodeAndTranscode方法中

    public Resource<Z> decodeFromSource() throws Exception {
    
        Resource<T> decoded = decodeSource();
    
        return transformEncodeAndTranscode(decoded);
    
    }
    

    transformEncodeAndTranscode方法的返回值也是一个Resource对象,不过他的泛型是不一样的,一个Z 一个T,先看看这个方法吧

    Q42

    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);
    
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
    
            logWithTimeAndKey("Transcoded transformed from source", startTime);
    
        }
    
        return result;
    
    }
    

    注意到 Resource<Z> result = transcode(transformed) 这段代码,又调用trancode(transformed)来看看

    Q43

    private Resource<Z> transcode(Resource<T> transformed) {
    
        if (transformed == null) {
    
            return null;
    
        }
    
        return transcoder.transcode(transformed);
    
    }
    

    transcoder是在DecodeJob初始化的时候传来,初始化的时候是在Engine.load(Q26) 的方法中,而调用Engine.load是在GenericRequest的onSizeReady(Q24)中,通过loadProvider.getTranscoder()获取出来的

    而这个loadProvider就是Q25中创建出来的 FixedLoadProvider并传入3个参数,而他获取getTranscoder()就是Q25中初始化传入的GifBitmapWrapperDrawableTranscoder,我们看一下GifBitmapWrapperDrawableTranscoder中的transcode方法

    Q44

    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();
    
        }
    
        // This is unchecked but always safe, anything that extends a Drawable can be safely cast to a Drawable.
    
        return (Resource<GlideDrawable>) result;
    
    }
    

    可以看到,它是先从GifBitmapWrapperResource中取出GifBitmapWrapper,再从GifBitmapWrapper中取出BitmapResource (Q38,39,40,41 有解释了),然后判断是否为空之后调用bitmapDrawableResourceTranscoder.transcode(bitmapResource),否则调用gifBitmap.getGifResource()方法加载一个gif图片。跟GifBitmapWrapperDrawableTranscoder一样,只需要知道这个bitmapDrawableResourceTranscoder是GlideBitmapDrawableTranscoder对象就可以了,否则分析会不完。所以接下来就会调用GlideBitmapDrawableTranscoder中的transcode方法将BitmapResource 传进去。

    Q45

    @Override
    public Resource<GlideBitmapDrawable> transcode(Resource<Bitmap> toTranscode) {
    
        GlideBitmapDrawable drawable = new GlideBitmapDrawable(resources, toTranscode.get());
    
        return new GlideBitmapDrawableResource(drawable, bitmapPool);
    
    }
    

    这里面又做了两个动作,new GlideBitmapDrawable对象,并获取出BitmapResource 中的Bitmap封装到里面,在返回一个GlideBitmapDrawableResource,又把GlideBitmapDrawable传进去返回,所以Q44当中返回的就是GlideBitmapDrawableResource对象,返回的就是Resource<GlideBitmapDrawable>,Q42 中的这个Z就是GlideBitmapDrawable,所以我们回到Q44当中,这个Resource<? extends GlideDrawable> result 就是GlideBitmapDrawableResource<GlideBitmapDrawable> 将它返回到Q42 再返回到 Q30中再到Q27 (跨度又点大),也就是回到EngineRunnable的run方法中。

    @Override
    
    public void 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() 有够深的,decode返回的就是上面分析的Resource<GlideDrawable>,最后判断是否为空之后,调用onLoadComplete传进去,

    Q46

    private void onLoadComplete(Resource resource) {
    
        manager.onResourceReady(resource);
    
    }
    

    这个manager就是Q26 传的EngineJob对象,看看呗

    Q47

    @Override
    public void onResourceReady(final Resource<?> resource) {
    
        this.resource = resource;
    
        MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
    
    }
    

    将 Resource<?> resource赋值给成员变量之后,发送一个消息,把自己传过去。Handler 就是EngineJob中的静态内部类,在run方法运行后就一直在子线程中执行上面分析的逻辑代码,只有在这里的时候才通过handler回到子线程当中来,所以可以猜到,接下来的代码就是执行图片展示的代码。

    Q48

    private static class MainThreadCallback implements Handler.Callback {
    
        @Override
        public boolean handleMessage(Message message) {
    
            if (MSG_COMPLETE == message.what || MSG_EXCEPTION == message.what) {
    
                EngineJob job = (EngineJob) message.obj;
    
                if (MSG_COMPLETE == message.what) {
    
                    job.handleResultOnMainThread();
    
                } else {
    
                    job.handleExceptionOnMainThread();
    
                }
    
                return true;
    
            }
    
            return false;
    
        }
    
    }
    

    接下来就是调用 EngineJob 中的 handleResultOnMainThread方法,

    Q49

    private void handleResultOnMainThread() {
    
    ......
    
        for (ResourceCallback cb : cbs) {
    
            if (!isInIgnoredCallbacks(cb)) {
    
                engineResource.acquire();
    
                cb.onResourceReady(engineResource);
    
            }
    
        }
    
        // Our request is complete, so we can release the resource.
    
        engineResource.release();
    
    }
    

    看到一个for循环,遍历获取cbs,cbs是一个成员变量的集合private final List<ResourceCallback> cbs = new ArrayList<ResourceCallback>(),通过遍历获取到ResourceCallback ,那么ResourceCallback 添加是在什么时候的?在EngineJob的时候还有一个add的方法,

    Q50

    public void addCallback(ResourceCallback cb) {
    
            Util.assertMainThread();
    
            if (hasResource) {
    
                cb.onResourceReady(engineResource);
    
            } else if (hasException) {
    
                cb.onException(exception);
    
            } else {
    
                cbs.add(cb);
    
            }
    
    }
    

    最后就是cbs.add 将传进来的参数添加进集合中。这个addCallback方法就在Engine.load(Q26 )中调用的,而且是作为load的参数传进来的,我们在Q24Q25的时候有分析过,在GenericRequst.onSizeReady()方法中我们调用engine.load时传入很多参数,在最后一个参数的时候会传入一个this,也就是GenericRequst的本身,也就是GenericRequst实现了ResourceCallback接口,所以EngineJob最终调用的就是GenericRequst的onResourceReady方法。

    Q51

    public void onResourceReady(Resource<?> resource) {
    
        if (resource == null) {
    
            onException(new Exception("Expected to receive a Resource<R> with an object of " + transcodeClass
    
            + " inside, but instead got null."));
    
            return;
    
        }
    
        Object received = resource.get();
    
        if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
    
            releaseResource(resource);
    
            onException(new Exception("Expected to receive an object of "     + transcodeClass
    
                + " but instead got " + (received != null ? received.getClass() : "") + "{" + received + "}"
    
                + " inside Resource{" + resource + "}."
    
                + (received != null ? "" : " "
    
                + "To indicate failure return a null Resource object, "
    
                + "rather than a Resource object containing null data.")
    
                ));
    
            return;
    
        }
    
        if (!canSetResource()) {
    
            releaseResource(resource);
    
            // We can't set the status to complete before asking canSetResource().
    
            status = Status.COMPLETE;
    
            return;
    
        }
    
        onResourceReady(resource, (R) received);
    
    }
    

    先获取到resource.get() ,也就是上面分析的Q45 中的GlideBitmapDrawable, 再作为参数调用他的重载方法,

    Q52

    private void onResourceReady(Resource<?> resource, R result) {
    
        // We must call isFirstReadyResource before setting status.
    
        boolean isFirstResource = isFirstReadyResource();
    
        status = Status.COMPLETE;
    
        this.resource = resource;
    
        if (requestListener == null || !requestListener.onResourceReady(result, model, target, loadedFromMemoryCache,isFirstResource)) {
    
            GlideAnimation<R> animation = animationFactory.build(loadedFromMemoryCache, isFirstResource);
    
            target.onResourceReady(result, animation);
    
        }
    
        notifyLoadSuccess();
    
    }
    

    这里只要看到他的 target.onResourceReady(result, animation)方法,target知道,也就是前面分析(Q12)中的封装ImageView的GlideDrawableImageViewTarget对象,调用它的onResourceReady方法

    Q53

    public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {
    
        if (!resource.isAnimated()) {
    
            //TODO: Try to generalize this to other sizes/shapes.
    
            // This is a dirty hack that tries to make loading square thumbnails and then square full images less costly
    
            // by forcing both the smaller thumb and the larger version to have exactly the same intrinsic dimensions.
    
            // If a drawable is replaced in an ImageView by another drawable with different intrinsic dimensions,
    
            // the ImageView requests a layout. Scrolling rapidly while replacing thumbs with larger images triggers
    
            // lots of these calls and causes significant amounts of jank.
    
            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();
    
    }
    

    然后会调用父类的 super.onResourceReady(resource, animation);方法,

    Q54

    @Override
    public void onResourceReady(Z resource, GlideAnimation<? super Z> glideAnimation) {
    
        if (glideAnimation == null || !glideAnimation.animate(resource, this)) {
    
            setResource(resource);
    
        }
    
    }
    
    protected abstract void setResource(Z resource);
    

    父类只是调用了它的 setResource 方法,而setResource 方法是一个抽象方法,所以它会调用自己的setResource 方法,

    Q55

    @Override
    protected void setResource(GlideDrawable resource) {
    
        view.setImageDrawable(resource);
    
    }
    

    这个view就是封装的ImageView,然后将GlideDrawable 设置进来,至此,一个图片就展示出来了。

    总结:

    本文只是简单的分析,供个人参考

    参考:

    https://blog.csdn.net/guolin_blog/article/details/53939176

    相关文章

      网友评论

          本文标题:(拾起.笔记)源码分析记录之Glide源码分析(一)

          本文链接:https://www.haomeiwen.com/subject/weuyeftx.html