美文网首页
Glide源码流程分析(一)

Glide源码流程分析(一)

作者: 不需要任何 | 来源:发表于2018-09-18 20:06 被阅读13次

    流程:

    with

    public class Glide {
    
        ...
    
        public static RequestManager with(Context context) {
            RequestManagerRetriever retriever = RequestManagerRetriever.get();
            return retriever.get(context);
        }
    
        public static RequestManager with(Activity activity) {
            RequestManagerRetriever retriever = RequestManagerRetriever.get();
            return retriever.get(activity);
        }
    
        public static RequestManager with(FragmentActivity activity) {
            RequestManagerRetriever retriever = RequestManagerRetriever.get();
            return retriever.get(activity);
        }
    
        @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        public static RequestManager with(android.app.Fragment fragment) {
            RequestManagerRetriever retriever = RequestManagerRetriever.get();
            return retriever.get(fragment);
        }
    
        public static RequestManager with(Fragment fragment) {
            RequestManagerRetriever retriever = RequestManagerRetriever.get();
            return retriever.get(fragment);
        }
    }
    
    1. 初始化RequestManagerRetriever ,中文的意思就是请求管理者的领取人,我们从代码看他就是为了创建RequestManager
    2. 全是重载,传入的retriever.get();参数不同得到不同类型的RequestManager
    3. 继续探究retriever.get()
    public class RequestManagerRetriever implements Handler.Callback {
    
        private static final RequestManagerRetriever INSTANCE = new RequestManagerRetriever();
    
        private volatile RequestManager applicationManager;
    
        ...
    
        /**
         * Retrieves and returns the RequestManagerRetriever singleton.
         */
        public static RequestManagerRetriever get() {
            return INSTANCE;
        }
    
        private RequestManager getApplicationManager(Context context) {
            // Either an application context or we're on a background thread.
            if (applicationManager == null) {
                synchronized (this) {
                    if (applicationManager == null) {
                        // Normally pause/resume is taken care of by the fragment we add to the fragment or activity.
                        // However, in this case since the manager attached to the application will not receive lifecycle
                        // events, we must force the manager to start resumed using ApplicationLifecycle.
                        applicationManager = new RequestManager(context.getApplicationContext(),
                                new ApplicationLifecycle(), new EmptyRequestManagerTreeNode());
                    }
                }
            }
            return applicationManager;
        }
    
        public RequestManager get(Context context) {
            if (context == null) {
                throw new IllegalArgumentException("You cannot start a load on a null Context");
            } else if (Util.isOnMainThread() && !(context instanceof Application)) {
                if (context instanceof FragmentActivity) {
                    return get((FragmentActivity) context);
                } else if (context instanceof Activity) {
                    return get((Activity) context);
                } else if (context instanceof ContextWrapper) {
                    return get(((ContextWrapper) context).getBaseContext());
                }
            }
            return getApplicationManager(context);
        }
    
        public RequestManager get(FragmentActivity activity) {
            if (Util.isOnBackgroundThread()) {
                return get(activity.getApplicationContext());
            } else {
                assertNotDestroyed(activity);
                FragmentManager fm = activity.getSupportFragmentManager();
                return supportFragmentGet(activity, fm);
            }
        }
    
        public RequestManager get(Fragment fragment) {
            if (fragment.getActivity() == null) {
                throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");
            }
            if (Util.isOnBackgroundThread()) {
                return get(fragment.getActivity().getApplicationContext());
            } else {
                FragmentManager fm = fragment.getChildFragmentManager();
                return supportFragmentGet(fragment.getActivity(), fm);
            }
        }
    
        @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        public RequestManager get(Activity activity) {
            if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
                return get(activity.getApplicationContext());
            } else {
                assertNotDestroyed(activity);
                android.app.FragmentManager fm = activity.getFragmentManager();
                return fragmentGet(activity, fm);
            }
        }
    
        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
        private static void assertNotDestroyed(Activity activity) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed()) {
                throw new IllegalArgumentException("You cannot start a load for a destroyed activity");
            }
        }
    
        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
        public RequestManager get(android.app.Fragment fragment) {
            if (fragment.getActivity() == null) {
                throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");
            }
            if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
                return get(fragment.getActivity().getApplicationContext());
            } else {
                android.app.FragmentManager fm = fragment.getChildFragmentManager();
                return fragmentGet(fragment.getActivity(), fm);
            }
        }
    
        @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;
        }
    
        @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;
        }
    
        SupportRequestManagerFragment getSupportRequestManagerFragment(final FragmentManager fm) {
            SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
            if (current == null) {
                current = pendingSupportRequestManagerFragments.get(fm);
                if (current == null) {
                    current = new SupportRequestManagerFragment();
                    pendingSupportRequestManagerFragments.put(fm, current);
                    fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
                    handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
                }
            }
            return current;
        }
    
        RequestManager supportFragmentGet(Context context, FragmentManager fm) {
            SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);
            RequestManager requestManager = current.getRequestManager();
            if (requestManager == null) {
                requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
                current.setRequestManager(requestManager);
            }
            return requestManager;
        }
    
        ...
    }
    
    1. 主要分为两个类型主要:Application非Application两种,每个方法的前面都是判断先不管,看后面会发现Application最后是通过getApplicationManager方法来得到requestManager的,而非Application是通过supportFragmentGet或者fragmentGet方法来获得的。
    2. 探究getApplicationManager方法:我们new直接创建一个RequestManager对象传入Application的上下文。
    3. 而其他情况就探究fragmentGet方法,在这之前我们看见该方法多传入了FragmentMananger,奇怪为什么传入这个东西呢,接着看fragmentGet方法内,不管怎么样执行都会向Activity添加一个隐藏的fragment,为什么要添加一个隐藏的fragment?很简单,因为我们的Glide必须监听Activity的生命流程,如果在加载过程中,我们的Activity死掉了我们的Glide岂不是就没有比较继续执行了,我们的Glide没办法监听到Activity的生死,那就可以通过fragment来监听,因为fragment的生命周期和Activity是绑定的嘛。 至于为什么传入Application就可以直接创建,因为Glide依然都和APP共生死了,我们就没必要关系Glide的销毁问题了。
    4. 值得注意一点就是,如果传入的时候,当前线程属于主线程的话,Glide也会按照Application的流程执行

    load

    前文已经提到了创建了始终是RequestManager 然后我们看看调用了load()方法这里我们知道如果看过源码都知道load有蛮多的重载方法。所以我们只要URLload方法:

    public class RequestManager implements LifecycleListener {
    
        ...
    
        /**
         * Returns a request builder to load the given {@link String}.
         * signature.
         *
         * @see #fromString()
         * @see #load(Object)
         *
         * @param string A file path, or a uri or url handled by {@link com.bumptech.glide.load.model.UriLoader}.
         */
        public DrawableTypeRequest<String> load(String string) {
            return (DrawableTypeRequest<String>) fromString().load(string);
        }
    
        /**
         * Returns a request builder that loads data from {@link String}s using an empty signature.
         *
         * <p>
         *     Note - this method caches data using only the given String as the cache key. If the data is a Uri outside of
         *     your control, or you otherwise expect the data represented by the given String to change without the String
         *     identifier changing, Consider using
         *     {@link GenericRequestBuilder#signature(Key)} to mixin a signature
         *     you create that identifies the data currently at the given String that will invalidate the cache if that data
         *     changes. Alternatively, using {@link DiskCacheStrategy#NONE} and/or
         *     {@link DrawableRequestBuilder#skipMemoryCache(boolean)} may be appropriate.
         * </p>
         *
         * @see #from(Class)
         * @see #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);
            if (modelClass != null && streamModelLoader == null && fileDescriptorModelLoader == null) {
                throw new IllegalArgumentException("Unknown type " + modelClass + ". You must provide a Model of a type for"
                        + " which there is a registered ModelLoader, if you are using a custom model, you must first call"
                        + " Glide#register with a ModelLoaderFactory for your custom model class");
            }
            return optionsApplier.apply(
                    new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
                            glide, requestTracker, lifecycle, optionsApplier));
        }
    
        ...
    
    }
    
    
        class OptionsApplier {
    
            public <A, X extends GenericRequestBuilder<A, ?, ?, ?>> X apply(X builder) {
                if (options != null) {
                    options.apply(builder);
                }
                return builder;
            }
        }
    
    
    • 前面都不需要解释太多,我们只需要看见最后的调用loadGeneric方法即可,传入的是String.class,重点看看这个方法里 ,我们组要创建了两个图片下载器下载器:streamModelLoaderfileDescriptorModelLoader,这个不过多研究,但是我们得知道的是传入的modelClass创建了是一个StreamStringLoader他同样实现ModelLoader的接口。
    • 最后我们创建了一个DrawableTypeRequest对象它持有下载器,上下文,生命周期等等的一个请求对象,然后调用optionsApplier.apply()方法
    • 我们查看optionsApplier.apply()方法,可以得出相关结论,就是传出和传出的对象既然相同,所以问该方法要么是对该对象进行检查,或者是修改或者添加某样属性,这里我们options单词,大胆猜测肯定是和剪切有关的属性。

    接着我们查看诉所谓的DrawableTypeRequest

    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;
        }
    
        /**
         * Attempts to always load the resource as a {@link android.graphics.Bitmap}, even if it could actually be animated.
         *
         * @return A new request builder for loading a {@link android.graphics.Bitmap}
         */
        public BitmapTypeRequest<ModelType> asBitmap() {
            return optionsApplier.apply(new BitmapTypeRequest<ModelType>(this, streamModelLoader,
                    fileDescriptorModelLoader, optionsApplier));
        }
    
        /**
         * Attempts to always load the resource as a {@link com.bumptech.glide.load.resource.gif.GifDrawable}.
         * <p>
         *     If the underlying data is not a GIF, this will fail. As a result, this should only be used if the model
         *     represents an animated GIF and the caller wants to interact with the GIfDrawable directly. Normally using
         *     just an {@link DrawableTypeRequest} is sufficient because it will determine whether or
         *     not the given data represents an animated GIF and return the appropriate animated or not animated
         *     {@link android.graphics.drawable.Drawable} automatically.
         * </p>
         *
         * @return A new request builder for loading a {@link com.bumptech.glide.load.resource.gif.GifDrawable}.
         */
        public GifTypeRequest<ModelType> asGif() {
            return optionsApplier.apply(new GifTypeRequest<ModelType>(this, streamModelLoader, optionsApplier));
        }
    
        ...
    }
    

    上面方法主要提供了两种方法asBitmap()asGif()这个不用多讲主要是把他转换为动态或者是静态的请求。

    最后我们回到起点:

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

    中的load方法 ,我们调用的对象是DrawableTypeRequest上面返回的传入的是String即URL,所以继续深入DrawableTypeRequest对象查看:

    DrawableTypeRequest#load

      @Override
        public DrawableRequestBuilder<ModelType> load(ModelType model) {
            super.load(model);
            return this;
        }
    

    他调用的是父类DrawableRequestBuilder方法:

    public class DrawableRequestBuilder<ModelType>
            extends GenericRequestBuilder<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable>
            implements BitmapOptions, DrawableOptions {
    
        DrawableRequestBuilder(Context context, Class<ModelType> modelClass,
                LoadProvider<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable> loadProvider, Glide glide,
                RequestTracker requestTracker, Lifecycle lifecycle) {
            super(context, modelClass, loadProvider, GlideDrawable.class, glide, requestTracker, lifecycle);
            // Default to animating.
            crossFade();
        }
    
        public DrawableRequestBuilder<ModelType> thumbnail(
                DrawableRequestBuilder<?> thumbnailRequest) {
            super.thumbnail(thumbnailRequest);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> thumbnail(
                GenericRequestBuilder<?, ?, ?, GlideDrawable> thumbnailRequest) {
            super.thumbnail(thumbnailRequest);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> thumbnail(float sizeMultiplier) {
            super.thumbnail(sizeMultiplier);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> sizeMultiplier(float sizeMultiplier) {
            super.sizeMultiplier(sizeMultiplier);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> decoder(ResourceDecoder<ImageVideoWrapper, GifBitmapWrapper> decoder) {
            super.decoder(decoder);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> cacheDecoder(ResourceDecoder<File, GifBitmapWrapper> cacheDecoder) {
            super.cacheDecoder(cacheDecoder);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> encoder(ResourceEncoder<GifBitmapWrapper> encoder) {
            super.encoder(encoder);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> priority(Priority priority) {
            super.priority(priority);
            return this;
        }
    
        public DrawableRequestBuilder<ModelType> transform(BitmapTransformation... transformations) {
            return bitmapTransform(transformations);
        }
    
        public DrawableRequestBuilder<ModelType> centerCrop() {
            return transform(glide.getDrawableCenterCrop());
        }
    
        public DrawableRequestBuilder<ModelType> fitCenter() {
            return transform(glide.getDrawableFitCenter());
        }
    
        public DrawableRequestBuilder<ModelType> bitmapTransform(Transformation<Bitmap>... bitmapTransformations) {
            GifBitmapWrapperTransformation[] transformations =
                    new GifBitmapWrapperTransformation[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);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> transcoder(
                ResourceTranscoder<GifBitmapWrapper, GlideDrawable> transcoder) {
            super.transcoder(transcoder);
            return this;
        }
    
        public final DrawableRequestBuilder<ModelType> crossFade() {
            super.animate(new DrawableCrossFadeFactory<GlideDrawable>());
            return this;
        }
    
        public DrawableRequestBuilder<ModelType> crossFade(int duration) {
            super.animate(new DrawableCrossFadeFactory<GlideDrawable>(duration));
            return this;
        }
    
        public DrawableRequestBuilder<ModelType> crossFade(int animationId, int duration) {
            super.animate(new DrawableCrossFadeFactory<GlideDrawable>(context, animationId,
                    duration));
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> dontAnimate() {
            super.dontAnimate();
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> animate(ViewPropertyAnimation.Animator animator) {
            super.animate(animator);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> animate(int animationId) {
            super.animate(animationId);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> placeholder(int resourceId) {
            super.placeholder(resourceId);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> placeholder(Drawable drawable) {
            super.placeholder(drawable);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> fallback(Drawable drawable) {
            super.fallback(drawable);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> fallback(int resourceId) {
            super.fallback(resourceId);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> error(int resourceId) {
            super.error(resourceId);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> error(Drawable drawable) {
            super.error(drawable);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> listener(
                RequestListener<? super ModelType, GlideDrawable> requestListener) {
            super.listener(requestListener);
            return this;
        }
        @Override
        public DrawableRequestBuilder<ModelType> diskCacheStrategy(DiskCacheStrategy strategy) {
            super.diskCacheStrategy(strategy);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> skipMemoryCache(boolean skip) {
            super.skipMemoryCache(skip);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> override(int width, int height) {
            super.override(width, height);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> sourceEncoder(Encoder<ImageVideoWrapper> sourceEncoder) {
            super.sourceEncoder(sourceEncoder);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> dontTransform() {
            super.dontTransform();
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> signature(Key signature) {
            super.signature(signature);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> load(ModelType model) {
            super.load(model);
            return this;
        }
    
        @Override
        public DrawableRequestBuilder<ModelType> clone() {
            return (DrawableRequestBuilder<ModelType>) super.clone();
        }
    
        @Override
        public Target<GlideDrawable> into(ImageView view) {
            return super.into(view);
        }
    
        @Override
        void applyFitCenter() {
            fitCenter();
        }
    
        @Override
        void applyCenterCrop() {
            centerCrop();
        }
    }
    

    我们查看他只不过就将URL添加进request的属性里面而已,当然这有相当多的API是我们使用的时候能接触到的,如placeholder()方法、error()方法、diskCacheStrategy()方法等等,他其实就是传入属性,然后返回对象,这样达到了链式操作。

    into

    接下来进入重点,into当然和前文一样还是交给父类的into方法那我们来看看into方法吧

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

    前面先不管,这个为了 transfrom 而设计的,所以我们直接跳过看最后的return代码,他调用的是glide.buildImageViewTarget 继续查看代码:

    Glide.buildImageViewTarget :

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

    这里我们可以看见通过工厂模式创建Target,Target中文名即为目标这里指的是我们需要展示的目标。接下来继续进入:

    ImageViewTargetFactory#buildTarget:

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

    这里我们看见我们通过传入的clazz参数不桶从而创建出不同的Target对象,这是一个典型抽象工厂模式。至于clazz我直接在这里简单梳理,除非调用asBitmap()我们创建的是BitmapImageViewTarget对象,一般情况下就是我们不设置的情况下,我们设置的是GlideDrawableImageViewTarget对象,所以我们这里返回的也是他。

    所以我们回到上面代码的最后一行调用into方法中

    GenericRequestBuilder#into():

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

    这里我们看见他真真正正创建了Request,并且把它传入了target这个目标展示对象,然后target这个目标加入了Glide的生命对象中,然后调用requestTracker.runRequest方法执行这个请求。到这里可能大家有些懵逼,所以我们先拉回buildRequest()看看他是怎么创建的:

    GenericRequestBuilder#buildRequest:

    
        private Request buildRequest(Target<TranscodeType> target) {
            if (priority == null) {
                priority = Priority.NORMAL;
            }
            return buildRequestRecursive(target, null);
        }
    
        private Request buildRequestRecursive(Target<TranscodeType> target, ThumbnailRequestCoordinator parentCoordinator) {
            if (thumbnailRequestBuilder != null) {
                if (isThumbnailBuilt) {
                    throw new IllegalStateException("You cannot use a request as both the main request and a thumbnail, "
                            + "consider using clone() on the request(s) passed to thumbnail()");
                }
                // Recursive case: 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 = new ThumbnailRequestCoordinator(parentCoordinator);
                Request fullRequest = obtainRequest(target, sizeMultiplier, priority, coordinator);
                // Guard against infinite recursion.
                isThumbnailBuilt = true;
                // Recursively generate thumbnail requests.
                Request thumbRequest = thumbnailRequestBuilder.buildRequestRecursive(target, coordinator);
                isThumbnailBuilt = false;
                coordinator.setRequests(fullRequest, thumbRequest);
                return coordinator;
            } else if (thumbSizeMultiplier != null) {
                // Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
                ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
                Request fullRequest = obtainRequest(target, sizeMultiplier, priority, coordinator);
                Request thumbnailRequest = obtainRequest(target, thumbSizeMultiplier, getThumbnailPriority(), coordinator);
                coordinator.setRequests(fullRequest, thumbnailRequest);
                return coordinator;
            } else {
                // Base case: no thumbnail.
                return obtainRequest(target, sizeMultiplier, priority, parentCoordinator);
            }
        }
        
           private Request obtainRequest(Target<TranscodeType> target, float sizeMultiplier, Priority priority,
                RequestCoordinator requestCoordinator) {
            return GenericRequest.obtain(
                    loadProvider,
                    model,
                    signature,
                    context,
                    priority,
                    target,
                    sizeMultiplier,
                    placeholderDrawable,
                    placeholderId,
                    errorPlaceholder,
                    errorId,
                    fallbackDrawable,
                    fallbackResource,
                    requestListener,
                    requestCoordinator,
                    glide.getEngine(),
                    transformation,
                    transcodeClass,
                    isCacheable,
                    animationFactory,
                    overrideWidth,
                    overrideHeight,
                    diskCacheStrategy);
        }
        
    
    • 我们看见先从看的当然是Request是如何创建的这是主线,这里调用的是obtainRequest方法执行的,然后这里大半部分代码都有一个thumbnail 单词,如果你有相关写图库的经历,就知道这个单词与压缩图有关,所以我们大胆猜测与压缩图有关系的代码,接着我们就交给了GenericRequest.obtain代码:

    GenericRequest#obtain

    从传入的参数印证了Request是请求类的说法,他传入的都是与请求先关的属性。

    public static <A, T, Z, R> GenericRequest<A, T, Z, R> obtain(
                LoadProvider<A, T, Z, R> loadProvider,
                A model,
                Key signature,
                Context context,
                Priority priority,
                Target<R> target,
                float sizeMultiplier,
                Drawable placeholderDrawable,
                int placeholderResourceId,
                Drawable errorDrawable,
                int errorResourceId,
                Drawable fallbackDrawable,
                int fallbackResourceId,
                RequestListener<? super A, R> requestListener,
                RequestCoordinator requestCoordinator,
                Engine engine,
                Transformation<Z> transformation,
                Class<R> transcodeClass,
                boolean isMemoryCacheable,
                GlideAnimationFactory<R> animationFactory,
                int overrideWidth,
                int overrideHeight,
                DiskCacheStrategy diskCacheStrategy) {
            @SuppressWarnings("unchecked")
            GenericRequest<A, T, Z, R> request = (GenericRequest<A, T, Z, R>) REQUEST_POOL.poll();
            if (request == null) {
                request = new GenericRequest<A, T, Z, R>();
            }
            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;
        }
        
        
        private void init(
                LoadProvider<A, T, Z, R> loadProvider,
                A model,
                Key signature,
                Context context,
                Priority priority,
                Target<R> target,
                float sizeMultiplier,
                Drawable placeholderDrawable,
                int placeholderResourceId,
                Drawable errorDrawable,
                int errorResourceId,
                Drawable fallbackDrawable,
                int fallbackResourceId,
                RequestListener<? super A, R> requestListener,
                RequestCoordinator requestCoordinator,
                Engine engine,
                Transformation<Z> transformation,
                Class<R> transcodeClass,
                boolean isMemoryCacheable,
                GlideAnimationFactory<R> animationFactory,
                int overrideWidth,
                int overrideHeight,
                DiskCacheStrategy diskCacheStrategy) {
            this.loadProvider = loadProvider;
            this.model = model;
            this.signature = signature;
            this.fallbackDrawable = fallbackDrawable;
            this.fallbackResourceId = fallbackResourceId;
            this.context = context.getApplicationContext();
            this.priority = priority;
            this.target = target;
            this.sizeMultiplier = sizeMultiplier;
            this.placeholderDrawable = placeholderDrawable;
            this.placeholderResourceId = placeholderResourceId;
            this.errorDrawable = errorDrawable;
            this.errorResourceId = errorResourceId;
            this.requestListener = requestListener;
            this.requestCoordinator = requestCoordinator;
            this.engine = engine;
            this.transformation = transformation;
            this.transcodeClass = transcodeClass;
            this.isMemoryCacheable = isMemoryCacheable;
            this.animationFactory = animationFactory;
            this.overrideWidth = overrideWidth;
            this.overrideHeight = overrideHeight;
            this.diskCacheStrategy = diskCacheStrategy;
            status = Status.PENDING;
    
            // We allow null models by just setting an error drawable. Null models will always have empty providers, we
            // simply skip our sanity checks in that unusual case.
            if (model != null) {
                check("ModelLoader", loadProvider.getModelLoader(), "try .using(ModelLoader)");
                check("Transcoder", loadProvider.getTranscoder(), "try .as*(Class).transcode(ResourceTranscoder)");
                check("Transformation", transformation, "try .transform(UnitTransformation.get())");
                if (diskCacheStrategy.cacheSource()) {
                    check("SourceEncoder", loadProvider.getSourceEncoder(),
                            "try .sourceEncoder(Encoder) or .diskCacheStrategy(NONE/RESULT)");
                } else {
                    check("SourceDecoder", loadProvider.getSourceDecoder(),
                            "try .decoder/.imageDecoder/.videoDecoder(ResourceDecoder) or .diskCacheStrategy(ALL/SOURCE)");
                }
                if (diskCacheStrategy.cacheSource() || diskCacheStrategy.cacheResult()) {
                    // TODO if(resourceClass.isAssignableFrom(InputStream.class) it is possible to wrap sourceDecoder
                    // and use it instead of cacheDecoder: new FileToStreamDecoder<Z>(sourceDecoder)
                    // in that case this shouldn't throw
                    check("CacheDecoder", loadProvider.getCacheDecoder(),
                            "try .cacheDecoder(ResouceDecoder) or .diskCacheStrategy(NONE)");
                }
                if (diskCacheStrategy.cacheResult()) {
                    check("Encoder", loadProvider.getEncoder(),
                            "try .encode(ResourceEncoder) or .diskCacheStrategy(NONE/SOURCE)");
                }
            }
        }
    

    可以看到我们是new出来了GenericRequest对象,如果没有从请求池里面拿到的话,然后调用init方法,我们看见只是个request进行属性的复制而已。

    相关文章

      网友评论

          本文标题:Glide源码流程分析(一)

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