Glide加载图片流程源码解析(1)

作者: JJQ3 | 来源:发表于2017-08-08 09:37 被阅读135次

    网上Glide源码解析的资料比较多,但鱼龙混杂,so我决定还是自己跟一遍源码吧,看源码真的是一件爆炸的事,好几次想放弃,但最后还是坚持下来了,唉。
    首先先来捋一遍Glide的具体用法,从具体用法出发我们再来分析Glide内部都是怎么来实现这些方法的。

    这是我从网上找来的Glide的主要功能示意图,这张图一目了然的显示了Glide能实现的功能。

    功能示意图.png

    先来看Glide最基础的图片加载用法:

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

    这里的load()方法就是指定要加载的图片资源,可以是网络图片,也可以是本地图片,资源图片,二进制流,Uri对象等等。
    当然我们也可以在加载图片的基础上做很多事,比如设置缺省图,加载失败的时候显示的图,设置图片尺寸,加载动画等。。。就像这样:

    Glide
    .with(context)
    .load(imageUrl)
    .placeholder(R.mipmap.ic_launcher)  //占位图
    .error(R.mipmap.ic_launcher)        //加载错误显示的图
    .animate(R.anim.anim)               //加载动画
    .override(88, 88)                   //图片尺寸
    .into(imageView);
    

    这里都是采用多态形式来实现的。
    Glide还可以指定要加载的图片格式。什么意思呢?就比如我这里有一个gif图片的图片链接地址,那我什么都不指定,用Glide加载,加载显示出来的就是gif图,但是如果我加了一个asBitmap()方法,指定加载的必须是静态图片,那么Glide就会只加载gif图的第一帧。
    ok,接下来看Glide的图片缓存:
    设置磁盘缓存

    Glide.with(this).load(url).diskCacheStrategy(DiskCacheStrategy.ALL).into(imageView);
    

    对应的缓存参数如下:
    缓存参数说明
    DiskCacheStrategy.NONE:不缓存任何图片,即禁用磁盘缓存
    DiskCacheStrategy.ALL :缓存原始图片 & 转换后的图片(默认)
    DiskCacheStrategy.SOURCE:只缓存原始图片(原来的全分辨率的图像,即不缓存转换后的图片)
    DiskCacheStrategy.RESULT:只缓存转换后的图片(即最终的图像:降低分辨率后 / 或者转换后 ,不缓存原始图片

    ok,基本用法讲解完毕,之后就从用法出发,开始分析Glide的源码。
    先来看with()方法,with方法传了一个Context进去,其实很简单,就是绑定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);
        }
    

    with()方法有很多重构方法,其实也就是参数不同而已,实现里可以看到都是跟RequestManagerRetriever这个类有关,RequestManagerRetriever.get()方法从代码里可以看到是为了得到它的单例,那就来看看RequestManagerRetriever这个类,先看下面这三个我抽取出来的方法:

    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);
            }
        }
    
    private RequestManager getApplicationManager(Context context) {
            if (applicationManager == null) {
                synchronized (this) {
                    if (applicationManager == null) {
                        applicationManager = new RequestManager(context.getApplicationContext(),
                                new ApplicationLifecycle(), new EmptyRequestManagerTreeNode());
                    }
                }
            }
    
            return applicationManager;
        }
    

    第一个方法中context传进来以后把FragmentActivity,Activity,ContextWrapper都分流出去,除了这三种情况之外(其实也就是application context)都return getApplicationManager(context)也就是上面代码中的第三个方法。从上述代码可以看出,当传入的context是application或者在子线程中,那么最后都会调用getApplicationManager,在getApplicationManager(Context context)方法中,创建了一个RequestManager对象,因为Application的生命周期是跟着app的生命周期的,所以当传入的context为application的时候Glide没有进行任何关于生命周期的判断。先来看另外一种也就是当传入Activity这些的时候:

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

    我们发现到最后也是创建了一个RequestManager对象,从后面两个方法可以看出,不管你context传入的是Activity还是FragmentActivitiy,都会在Activity的基础上创建一个Fragment,这是为什么呢?因为Glide无法监听到Activity的生命周期,所以往Activity中添加一个Fragment来监听Fragment的生命周期,因为如果Activity消亡了,Fragment当然也就消亡了,具体代码看下面,不过传入的参数跟之前Application的不同,这里的SupportRequestManagerFragment的current.getLifecycle()方法我们进去会发现这其实是一个继承了Fragment的类,也就是往Activity里添加的Fragment,lifecycle实现了各种生命周期的方法:

    @Override
        public void onStart() {
            super.onStart();
            lifecycle.onStart();
        }
    
        @Override
        public void onStop() {
            super.onStop();
            lifecycle.onStop();
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            lifecycle.onDestroy();
        }
    

    ok那现在回到RequestManager这个类,实现了LifecycleListener接口:

    public interface LifecycleListener {
    
        /**
         * Callback for when {@link android.app.Fragment#onStart()}} or {@link android.app.Activity#onStart()} is called.
         */
        void onStart();
    
        /**
         * Callback for when {@link android.app.Fragment#onStop()}} or {@link android.app.Activity#onStop()}} is called.
         */
        void onStop();
    
        /**
         * Callback for when {@link android.app.Fragment#onDestroy()}} or {@link android.app.Activity#onDestroy()} is
         * called.
         */
        void onDestroy();
    }
    

    在RequestManager类中分别在这三个生命周期方法中实现了各自的操作,操作代码全都在RequestTracker这个类里,这个类主要负责跟踪,取消,重启在进程中的或者已经完成了或者已经失败了的请求,看RequestTracker可知其实就是在Glide内部维护了一个Request请求的list:

    public class RequestTracker {
        private final Set<Request> requests = Collections.newSetFromMap(new WeakHashMap<Request, Boolean>());
        @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
        private final List<Request> pendingRequests = new ArrayList<Request>();
    
        private boolean isPaused;
        public void runRequest(Request request) {
            requests.add(request);
            if (!isPaused) {
                request.begin();
            } else {
                pendingRequests.add(request);
            }
        }
    
        void addRequest(Request request) {
            requests.add(request);
        }
    
        public void removeRequest(Request request) {
            requests.remove(request);
            pendingRequests.remove(request);
        }
    
        public boolean isPaused() {
            return isPaused;
        }
    
        public void pauseRequests() {
            isPaused = true;
            for (Request request : Util.getSnapshot(requests)) {
                if (request.isRunning()) {
                    request.pause();
                    pendingRequests.add(request);
                }
            }
        }
    
        public void resumeRequests() {
            isPaused = false;
            for (Request request : Util.getSnapshot(requests)) {
                if (!request.isComplete() && !request.isCancelled() && !request.isRunning()) {
                    request.begin();
                }
            }
            pendingRequests.clear();
        }
    
        public void clearRequests() {
            for (Request request : Util.getSnapshot(requests)) {
                request.clear();
            }
            pendingRequests.clear();
        }
    
        public void restartRequests() {
            for (Request request : Util.getSnapshot(requests)) {
                if (!request.isComplete() && !request.isCancelled()) {
                    // Ensure the request will be restarted in onResume.
                    request.pause();
                    if (!isPaused) {
                        request.begin();
                    } else {
                        pendingRequests.add(request);
                    }
                }
            }
        }
    }
    

    其实给Glide添加生命周期的意义很简单,当你在一个Activity里去加载图片,当图片还没加载出来的时候用户把Activity消亡了,那图片加载的request是不是得取消,其实就是这么一个道理。

    ok,接下来来看load()方法,因为with(context)方法返回的是RequestManager,所以load()方法自然也就在RequestManager类里,可以看到:

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

    方法实现非常简单,先来看fromString(),点到fromString()方法发现其实就是调用了loadGeneric(String.class)方法,ok那就来看loadGeneric()方法:

    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类来创建不同的ModelLoader类,然后再把这些参数都穿进去创造一个DrawableTypeRequest对象返回回去,因为这里我参考的是load(url)加载网络图片链接,所以传进去的就是String,这个ModelLoader是干嘛的呢,接着往下看,Glide.buildStreamModelLoader(modelClass, context):

    /**
         * A method to build a {@link ModelLoader} for the given model that produces {@link InputStream}s using a registered
         * factory.
         *
         * @see #buildModelLoader(Class, Class, android.content.Context)
         */
        public static <T> ModelLoader<T, InputStream> buildStreamModelLoader(Class<T> modelClass, Context context) {
            return buildModelLoader(modelClass, InputStream.class, context);
        }
    
    //省略一大段代码
    
    public static <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass,
                Context context) {
             if (modelClass == null) {
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "Unable to load null model, setting placeholder only");
                }
                return null;
            }
            return Glide.get(context).getLoaderFactory().buildModelLoader(modelClass, resourceClass);
        }
    

    创建一个ModelLoader对象有什么用呢?其实就是为了提供inputStream输入流,可以看到该方法最后return了一个buildModelLoader(modelClass, resourceClass)的对象,接下来就进入到这个方法,这个方法在GenericLoaderFactory类里面,GenericLoaderFactory这个类其实比较短,所以全部简略的全部贴出来:

    public class GenericLoaderFactory {
        private final Map<Class/*T*/, Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/>> modelClassToResourceFactories =
                new HashMap<Class, Map<Class, ModelLoaderFactory>>();
        private final Map<Class/*T*/, Map<Class/*Y*/, ModelLoader/*T, Y*/>> cachedModelLoaders =
                new HashMap<Class, Map<Class, ModelLoader>>();
    
        private static final ModelLoader NULL_MODEL_LOADER = new ModelLoader() {
            @Override
            public DataFetcher getResourceFetcher(Object model, int width, int height) {
                throw new NoSuchMethodError("This should never be called!");
            }
    
            @Override
            public String toString() {
                return "NULL_MODEL_LOADER";
            }
        };
    
        private final Context context;
    
        public GenericLoaderFactory(Context context) {
           this.context = context.getApplicationContext();
        }
    
    
        public synchronized <T, Y> ModelLoaderFactory<T, Y> unregister(Class<T> modelClass, Class<Y> resourceClass) {
            cachedModelLoaders.clear();
    
            ModelLoaderFactory/*T, Y*/ result = null;
            Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> resourceToFactories = modelClassToResourceFactories.get(modelClass);
            if (resourceToFactories != null) {
                result = resourceToFactories.remove(resourceClass);
            }
            return result;
        }
    
        public synchronized <T, Y> ModelLoaderFactory<T, Y> register(Class<T> modelClass, Class<Y> resourceClass,
                ModelLoaderFactory<T, Y> factory) {
            cachedModelLoaders.clear();
    
            Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> resourceToFactories = modelClassToResourceFactories.get(modelClass);
            if (resourceToFactories == null) {
                resourceToFactories = new HashMap<Class/*Y*/, ModelLoaderFactory/*T, Y*/>();
                modelClassToResourceFactories.put(modelClass, resourceToFactories);
            }
    
            ModelLoaderFactory/*T, Y*/ previous = resourceToFactories.put(resourceClass, factory);
    
            if (previous != null) {
                // This factory may be being used by another model. We don't want to say it has been removed unless we
                // know it has been removed for all models.
                for (Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> factories : modelClassToResourceFactories.values()) {
                    if (factories.containsValue(previous)) {
                        previous = null;
                        break;
                    }
                }
            }
    
            return previous;
        }
    
        @Deprecated
        public synchronized <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass,
                Context context) {
            return buildModelLoader(modelClass, resourceClass);
        }
    
        public synchronized <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass) {
            ModelLoader<T, Y> result = getCachedLoader(modelClass, resourceClass);
            if (result != null) {
                // We've already tried to create a model loader and can't with the currently registered set of factories,
                // but we can't use null to demonstrate that failure because model loaders that haven't been requested
                // yet will be null in the cache. To avoid this, we use a special signal model loader.
                if (NULL_MODEL_LOADER.equals(result)) {
                    return null;
                } else {
                    return result;
                }
            }
    
            final ModelLoaderFactory<T, Y> factory = getFactory(modelClass, resourceClass);
            if (factory != null) {
                result = factory.build(context, this);
                cacheModelLoader(modelClass, resourceClass, result);
            } else {
                // We can't generate a model loader for the given arguments with the currently registered set of factories.
                cacheNullLoader(modelClass, resourceClass);
            }
            return result;
        }
    
        private <T, Y> void cacheNullLoader(Class<T> modelClass, Class<Y> resourceClass) {
            cacheModelLoader(modelClass, resourceClass, NULL_MODEL_LOADER);
        }
    
        private <T, Y> void cacheModelLoader(Class<T> modelClass, Class<Y> resourceClass, ModelLoader<T, Y> modelLoader) {
            Map<Class/*Y*/, ModelLoader/*T, Y*/> resourceToLoaders = cachedModelLoaders.get(modelClass);
            if (resourceToLoaders == null) {
                resourceToLoaders = new HashMap<Class/*Y*/, ModelLoader/*T, Y*/>();
                cachedModelLoaders.put(modelClass, resourceToLoaders);
            }
            resourceToLoaders.put(resourceClass, modelLoader);
        }
    
        private <T, Y> ModelLoader<T, Y> getCachedLoader(Class<T> modelClass, Class<Y> resourceClass) {
            Map<Class/*Y*/, ModelLoader/*T, Y*/> resourceToLoaders = cachedModelLoaders.get(modelClass);
            ModelLoader/*T, Y*/ result = null;
            if (resourceToLoaders != null) {
                result = resourceToLoaders.get(resourceClass);
            }
    
            return result;
        }
    
        private <T, Y> ModelLoaderFactory<T, Y> getFactory(Class<T> modelClass, Class<Y> resourceClass) {
            Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> resourceToFactories = modelClassToResourceFactories.get(modelClass);
            ModelLoaderFactory/*T, Y*/ result = null;
            if (resourceToFactories != null) {
                result = resourceToFactories.get(resourceClass);
            }
    
            if (result == null) {
                for (Class<? super T> registeredModelClass : modelClassToResourceFactories.keySet()) {
                    if (registeredModelClass.isAssignableFrom(modelClass)) {
                        Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> currentResourceToFactories =
                                modelClassToResourceFactories.get(registeredModelClass);
                        if (currentResourceToFactories != null) {
                            result = currentResourceToFactories.get(resourceClass);
                            if (result != null) {
                                break;
                            }
                        }
                    }
                }
            }
    
            return result;
        }
    }
    

    重点来看buildModelLoader方法,这里的T跟Y范型类在我的心路历程里其实就是String跟InputStream。我们可以看到其实我们是通过getFactory(modelClass, resourceClass)这个方法来创建了一个ModelLoaderFactory对象的,看getFactory方法可以看到我们其实就是从一个modelClassToResourceFactories的map获取一个ModelLoaderFactory对象,而且是要已经注册过了的,至于怎么判断是否注册过,就要回到Glide的构造方法:

    Glide(Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, Context context, DecodeFormat decodeFormat) {
            this.engine = engine;
            this.bitmapPool = bitmapPool;
            this.memoryCache = memoryCache;
            this.decodeFormat = decodeFormat;
            loaderFactory = new GenericLoaderFactory(context);
            mainHandler = new Handler(Looper.getMainLooper());
            bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat);
    
            dataLoadProviderRegistry = new DataLoadProviderRegistry();
    
            StreamBitmapDataLoadProvider streamBitmapLoadProvider =
                    new StreamBitmapDataLoadProvider(bitmapPool, decodeFormat);
            dataLoadProviderRegistry.register(InputStream.class, Bitmap.class, streamBitmapLoadProvider);
    
            FileDescriptorBitmapDataLoadProvider fileDescriptorLoadProvider =
                    new FileDescriptorBitmapDataLoadProvider(bitmapPool, decodeFormat);
            dataLoadProviderRegistry.register(ParcelFileDescriptor.class, Bitmap.class, fileDescriptorLoadProvider);
    
            ImageVideoDataLoadProvider imageVideoDataLoadProvider =
                    new ImageVideoDataLoadProvider(streamBitmapLoadProvider, fileDescriptorLoadProvider);
            dataLoadProviderRegistry.register(ImageVideoWrapper.class, Bitmap.class, imageVideoDataLoadProvider);
    
            GifDrawableLoadProvider gifDrawableLoadProvider =
                    new GifDrawableLoadProvider(context, bitmapPool);
            dataLoadProviderRegistry.register(InputStream.class, GifDrawable.class, gifDrawableLoadProvider);
    
            dataLoadProviderRegistry.register(ImageVideoWrapper.class, GifBitmapWrapper.class,
                    new ImageVideoGifDrawableLoadProvider(imageVideoDataLoadProvider, gifDrawableLoadProvider, bitmapPool));
    
            dataLoadProviderRegistry.register(InputStream.class, File.class, new StreamFileDataLoadProvider());
    
            register(File.class, ParcelFileDescriptor.class, new FileDescriptorFileLoader.Factory());
            register(File.class, InputStream.class, new StreamFileLoader.Factory());
            register(int.class, ParcelFileDescriptor.class, new FileDescriptorResourceLoader.Factory());
            register(int.class, InputStream.class, new StreamResourceLoader.Factory());
            register(Integer.class, ParcelFileDescriptor.class, new FileDescriptorResourceLoader.Factory());
            register(Integer.class, InputStream.class, new StreamResourceLoader.Factory());
            register(String.class, ParcelFileDescriptor.class, new FileDescriptorStringLoader.Factory());
            register(String.class, InputStream.class, new StreamStringLoader.Factory());
            register(Uri.class, ParcelFileDescriptor.class, new FileDescriptorUriLoader.Factory());
            register(Uri.class, InputStream.class, new StreamUriLoader.Factory());
            register(URL.class, InputStream.class, new StreamUrlLoader.Factory());
            register(GlideUrl.class, InputStream.class, new HttpUrlGlideUrlLoader.Factory());
            register(byte[].class, InputStream.class, new StreamByteArrayLoader.Factory());
    
            transcoderRegistry.register(Bitmap.class, GlideBitmapDrawable.class,
                    new GlideBitmapDrawableTranscoder(context.getResources(), bitmapPool));
            transcoderRegistry.register(GifBitmapWrapper.class, GlideDrawable.class,
                    new GifBitmapWrapperDrawableTranscoder(
                            new GlideBitmapDrawableTranscoder(context.getResources(), bitmapPool)));
    
            bitmapCenterCrop = new CenterCrop(bitmapPool);
            drawableCenterCrop = new GifBitmapWrapperTransformation(bitmapPool, bitmapCenterCrop);
    
            bitmapFitCenter = new FitCenter(bitmapPool);
            drawableFitCenter = new GifBitmapWrapperTransformation(bitmapPool, bitmapFitCenter);
        }
    

    这里注册了FileDescriptorFileLoader、StreamFileLoader等好几个factory,因为我们这里传入的是String跟InputStream所以我们得到的factory其实是StreamStringLoader,后面的那个fileDescriptorModeLoader方法跟这里类似,所以这里就不详述了。
    ok,到这里我们就回去,经过这么一串分析之后就生成了一个DrawableTypeRequest对象,那么DrawableTypeRequest究竟是什么呢。。接下来就来look下这个,代码比较少:

    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));
        }
    
        /**
         * {@inheritDoc}
         */
        public <Y extends Target<File>> Y downloadOnly(Y target) {
            return getDownloadOnlyRequest().downloadOnly(target);
        }
    
        /**
         * {@inheritDoc}
         */
        public FutureTarget<File> downloadOnly(int width, int height) {
            return getDownloadOnlyRequest().downloadOnly(width, height);
        }
    
        private GenericTranscodeRequest<ModelType, InputStream, File> getDownloadOnlyRequest() {
            return optionsApplier.apply(new GenericTranscodeRequest<ModelType, InputStream, File>(File.class, this,
                    streamModelLoader, InputStream.class, File.class, optionsApplier));
        }
    }
    

    眼神好的朋友们是不是已经发现了asBitmap()跟asGif()两个我们之前说用法上的方法了。经过了一层一层底层方法的穿来穿去之后,突然发现这两个方法是不是很舒服。其实很简单,就是分别创建了一个BitmapTypeRequest和GifTypeRequest,根据不同的request然后底层再去加载不同的图片格式。
    ok,接下去我们再回到开头,fromString()方法之后返回一个DrawableTypeRequest对象,然后就是调用这个对象的load(string)方法,我们看到load方法其实是跳到了父类DrawableRequestBuilder里,那就来看看它的父类:

    //省略一部分代码
        public DrawableRequestBuilder<ModelType> centerCrop() {
            return transform(glide.getDrawableCenterCrop());
        }
    
        @SuppressWarnings("unchecked")
        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);
        }
    
    
    
        /**
         * {@inheritDoc}
         *
         * @see #bitmapTransform(com.bumptech.glide.load.Transformation[])
         * @see #centerCrop()
         * @see #fitCenter()
         */
        @Override
        public DrawableRequestBuilder<ModelType> transform(Transformation<GifBitmapWrapper>... transformation) {
            super.transform(transformation);
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        public DrawableRequestBuilder<ModelType> transcoder(
                ResourceTranscoder<GifBitmapWrapper, GlideDrawable> transcoder) {
            super.transcoder(transcoder);
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        public final DrawableRequestBuilder<ModelType> crossFade() {
            super.animate(new DrawableCrossFadeFactory<GlideDrawable>());
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        public DrawableRequestBuilder<ModelType> crossFade(int duration) {
            super.animate(new DrawableCrossFadeFactory<GlideDrawable>(duration));
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        @Deprecated
        public DrawableRequestBuilder<ModelType> crossFade(Animation animation, int duration) {
            super.animate(new DrawableCrossFadeFactory<GlideDrawable>(animation, duration));
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        public DrawableRequestBuilder<ModelType> crossFade(int animationId, int duration) {
            super.animate(new DrawableCrossFadeFactory<GlideDrawable>(context, animationId,
                    duration));
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        public DrawableRequestBuilder<ModelType> dontAnimate() {
            super.dontAnimate();
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        public DrawableRequestBuilder<ModelType> animate(ViewPropertyAnimation.Animator animator) {
            super.animate(animator);
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        public DrawableRequestBuilder<ModelType> animate(int animationId) {
            super.animate(animationId);
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        @Deprecated
        @SuppressWarnings("deprecation")
        @Override
        public DrawableRequestBuilder<ModelType> animate(Animation animation) {
            super.animate(animation);
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        public DrawableRequestBuilder<ModelType> placeholder(int resourceId) {
            super.placeholder(resourceId);
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        @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;
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        public DrawableRequestBuilder<ModelType> error(int resourceId) {
            super.error(resourceId);
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        public DrawableRequestBuilder<ModelType> error(Drawable drawable) {
            super.error(drawable);
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        public DrawableRequestBuilder<ModelType> listener(
                RequestListener<? super ModelType, GlideDrawable> requestListener) {
            super.listener(requestListener);
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        public DrawableRequestBuilder<ModelType> diskCacheStrategy(DiskCacheStrategy strategy) {
            super.diskCacheStrategy(strategy);
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        public DrawableRequestBuilder<ModelType> skipMemoryCache(boolean skip) {
            super.skipMemoryCache(skip);
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        public DrawableRequestBuilder<ModelType> override(int width, int height) {
            super.override(width, height);
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        public DrawableRequestBuilder<ModelType> sourceEncoder(Encoder<ImageVideoWrapper> sourceEncoder) {
            super.sourceEncoder(sourceEncoder);
            return this;
        }
    
        /**
         * {@inheritDoc}
         */
        @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();
        }
    

    有没有觉得很亲切,之前用法里我们用到的很多api方法我们终于看到了,当然我们也看到了into()方法,load方法我们先来看看它父类的实现:

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

    其实就是做了一个状态的保存而已。
    ok,那接下来我们就开始分析into()方法,into()方法我逻辑理了n遍,实在太复杂了我的天,稍微注意力不集中一下就晕了。。ok,废话不多说,接着来,into()。

    首先,我们定位到DrawableTypeRequest的父类GenericRequestBuilder里的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));
        }
    

    前面一大堆讲的都是图片变化的问题,暂时先放到一边,先来看图片加载的过程,也就是最后一句话,先来看buildImageViewTarget(view, transcoderClass)方法:

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

    之前的分析中可以看出transcodedClass也就是TranscodeType的一个实体类,而TranscodeType也就是GlideDrawable类,知道了这个以后那就接着往下看:

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

    这里我们看到了三个类GlideDrawableImageViewTarget、BitmapImageViewTarget、DrawableImageViewTarget。在这里,我们也就创建了一个GlideDrawableImageViewTarget对象了。ok,我们知道了这个以后现在回过头去看之前的into(Y target)方法:

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

    ok,到这里我们终于发现发出加载图片请求的类了,也就是Request,Request类的具体子类的作用就是根据图片路径来加载图片到imageView上。这里Request对象是通过buildRequest(target)方法来创建的,ok,接下来看这个:

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

    buildRequest方法里调用了buildRequestRecursive方法,这个里面代码不少,我们先把图片变化的都忽略,就会发现主要的还是botainRequest()方法,然后看到return了一个GenericRequest.obtain(n个参数)的方法,这么多参数,乍看一下你会觉得很熟悉,placehoderId,errorId等,这些不都是我们最开始讲Glide的时候用的一些api方法莫,是不是有一种胜利在望的感觉。。ok,那就接着往下看obtain()方法,进入了GenericRequest类:

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

    乍看一下头已经晕了。。。放松一下,仔细看,我们发现传进来这么多参数以后,方法里先去创建了一个GenericRequest的实体类,然后调用了init方法,进去看,会发现全是一个赋值的一个过程,ok,既然是这样子,我们已经知道了request创建的整个过程了莫,这条路就差不多走到底了,差不多该回去了,那就再回到into方法。

    Request request = buildRequest(target);
            target.setRequest(request);
            lifecycle.addListener(target);
            requestTracker.runRequest(request);
    

    首先先把request绑定给了GlideDrawableImageViewTarget对象,为了就是不会被Glide之外的调用,然后我们看到,runRequest(request)方法,直觉告诉我们request对象创建出来之后执行代码应该就在这里了,那我们就进去看看,果然。。

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

    这个方法在RequestTracker类里,这个类是不是很熟悉,之前在讲with()方法的生命周期里提到过。这个方法里做了一个很简单的逻辑判断,如果这个时候不是暂停状态的话,request.begin()方法去执行request,否则就把该request存放到一个放着没有完成或者可能会重新去运行一遍的request的list里面。接着一步一步下去,进begin()方法。因为之前我们request的创建过程中一步一步下来到最后是return了一个GenericRequest.obtain(n个参数),所以begin()方法就应该在GenericRequest类里面,ok,定位到begin()方法:

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

    ok,这个beging()方法我们慢慢来分析,首先我们先来看model是什么?我们往前看,翻到GenericRequestBuilder的构造函数,然后创建它对象的过程发现model其实在我们这种情况下就是图片的链接地址,也就是load里传过来的东西,因为这里我们分析的是加载网络请求图片,所以也就是图片的链接。ok,知道了model是什么以后我们再来看这个方法,如果model是空的,那么就调用onException(null)方法,我们来看这个方法

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

    哦?这里有个备注:如果这里是缩略图请求怎么办?我思考了半天也是不解这里为什么会有个问号备注,当然这不是重点。这里把图片加载的状态设置了failed,然后调用了setErrorPlacehoder(e)方法,看方法名字就知道这是在设置错误缺省图。

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

    这里我们发现还有一个canNotifyStatusChanged这么一个变量,有一个监听状态是否改变的过程确保了安全性和正确性。再来看这两个方法获取了placeholder跟error的图片:

    private Drawable getErrorDrawable() {
            if (errorDrawable == null && errorResourceId > 0) {
                errorDrawable = context.getResources().getDrawable(errorResourceId);
            }
            return errorDrawable;
        }
    
    private Drawable getPlaceholderDrawable() {
            if (placeholderDrawable == null && placeholderResourceId > 0) {
                placeholderDrawable = context.getResources().getDrawable(placeholderResourceId);
            }
            return placeholderDrawable;
        }
    

    接下来来看target.onLoadFailed(e, error)这个方法,要找这个方法又得回到最初的地方,因为target其实也就是GenericRequestBuilder里的into方法里glide.buildImageView(),所以onLoadFailed方法也就应该在ImageViewTarget类里面。

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

    很easy,给view设置图片,当然这里我们还看到了设置缺省图:

     @Override
        public void onLoadStarted(Drawable placeholder) {
            view.setImageDrawable(placeholder);
        }
    

    ok,看完错误缺省图的加载过程之后我们再回到GenericRequest类的begin()方法,看源码就是一个走迷宫的过程,一条路走到底了,然后再回头继续走下一条路,注意力稍微有一点不集中,就懵了。。。来看if跟else,if(Util.isValidDimensions(overrideWidth, overrideHeight))看了下工具类里这个方法,也就是说如果宽度和高度都是指定的话,也就是固定的话,就调用onSizeReady(width, height)方法,不然的话就调用target.getSize(this)方法,ok,我们先来看getSize()方法,跟之前的onLoadFailed一样,target就是ImageViewTarget,但是在里面找不到getSize()方法,所以应该在他的父类里,也就是ViewTarget类里找到了这个方法:

    @Override
        public void getSize(SizeReadyCallback cb) {
            sizeDeterminer.getSize(cb);
        }
    
    private static class SizeDeterminer {
    
    private void notifyCbs(int width, int height) {
                for (SizeReadyCallback cb : cbs) {
                    cb.onSizeReady(width, height);
                }
                cbs.clear();
            }
            //省略代码。。。。。。
            public void getSize(SizeReadyCallback cb) {
                int currentWidth = getViewWidthOrParam();
                int currentHeight = getViewHeightOrParam();
                if (isSizeValid(currentWidth) && isSizeValid(currentHeight)) {
                    cb.onSizeReady(currentWidth, currentHeight);
                } else {
                    // We want to notify callbacks in the order they were added and we only expect one or two callbacks to
                    // be added a time, so a List is a reasonable choice.
                    if (!cbs.contains(cb)) {
                        cbs.add(cb);
                    }
                    if (layoutListener == null) {
                        final ViewTreeObserver observer = view.getViewTreeObserver();
                        layoutListener = new SizeDeterminerLayoutListener(this);
                        observer.addOnPreDrawListener(layoutListener);
                    }
                }
            }
    
           //省略一大段代码
            }
        }
    

    我们可以看到,这里其实根据imageView的width,height做了一系列的计算之后得出了图片应该显示的多宽跟多高。计算结束之后,我们可以看到在SizeDeterminer里面最后的最后还是调用了onSizeReady()方法。那我们就来看看这个方法里到底干了什么:

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

    ok我们在这里又看到了ModelLoader,是不是很惊喜是不是很惊讶,这里通过loadProvider创建了一个ModelLoader,这个loadProvider又是什么东西呢?这我们就得回去回去看了。让我们回到load()方法,还记得我们load()方法里在buildModelLoader()的时候通过getFactory()创建了一个ModelLoaderFactory嘛,我们在那里生成返回了一个DrawableTypeRequest对象,在创建DrawableTypeRequest的时候new出了一个FixedLoadProvider类,而这个loadProvider其实就是FixedLoadProvider类的一个封装类ChildLoadProvider的一个实体对象。我们可以看看GenericRequestBuilder类的构造函数:

    GenericRequestBuilder(Context context, Class<ModelType> modelClass,
                LoadProvider<ModelType, DataType, ResourceType, TranscodeType> loadProvider,
                Class<TranscodeType> transcodeClass, Glide glide, RequestTracker requestTracker, Lifecycle lifecycle) {
            this.context = context;
            this.modelClass = modelClass;
            this.transcodeClass = transcodeClass;
            this.glide = glide;
            this.requestTracker = requestTracker;
            this.lifecycle = lifecycle;
            this.loadProvider = loadProvider != null
                    ? new ChildLoadProvider<ModelType, DataType, ResourceType, TranscodeType>(loadProvider) : null;
    
            if (context == null) {
                throw new NullPointerException("Context can't be null");
            }
            if (modelClass != null && loadProvider == null) {
                throw new NullPointerException("LoadProvider must not be null");
            }
        }
    

    ok,之后我们再回到onSizeReady()方法,之后调用了modelLoader.getResourceFetcher(model, width, height)方法,这个又是干嘛的呢?进去看看,getResourceFetcher()方法在哪里呢。。我们看到之前DrawableTypeRequest的构造函数里其实把loadGeneric()方法中创建的两个modelLoader对象都封装到了ImageVideoModelLoader这个类里面并new出了一个对象,所以getResourceFetcher()应该在这个里面:

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

    因为我们现在是第一次调用Glide加载图片,所以生成一个HttpUrlFetch对象。这里绕来绕去其实最后getResourceFetch()方法最后还是返回一个ImageVideoFetcher对象。然后我们再回去onSizeReady()方法,然后就是把这些new出来的东西全部传到engine.load()方法里面去。也就是这句话:

    loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
                    priority, isMemoryCacheable, diskCacheStrategy, this);
    

    那接下去就来看看Engine呗,Engine这个类看注释主要是负责加载以及管理活跃的和已经缓存了的资源。我们先暂时不看缓存相关的东西,等会讲缓存的东西的时候再翻回来看,我们现在先看加载的整个流程。ok,那我们来看Engine这个类里的load方法:

    public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
                DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,
                Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
            Util.assertMainThread();
            long startTime = LogTime.getLogTime();
    
            final String id = fetcher.getId();
            EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
                    loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
                    transcoder, loadProvider.getSourceEncoder());
    
            EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
            if (cached != null) {
                cb.onResourceReady(cached);
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    logWithTimeAndKey("Loaded resource from cache", startTime, key);
                }
                return null;
            }
    
            EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
            if (active != null) {
                cb.onResourceReady(active);
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    logWithTimeAndKey("Loaded resource from active resources", startTime, key);
                }
                return null;
            }
    
            EngineJob current = jobs.get(key);
            if (current != null) {
                current.addCallback(cb);
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    logWithTimeAndKey("Added to existing load", startTime, key);
                }
                return new LoadStatus(cb, current);
            }
    
            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);
        }
    

    忽略缓存相关的代码,首先创建了个EngineJob对象,然后创建了一个DecodeJob对象,然后把这两个对象穿进去创建了EngineRunnable对象,之后start(),ok所以我们现在就来重点看一下 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()这个方法里面,进去:

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

    顾名思义,一个是从缓存里获取图片,不然就去执行decodeFromSource()方法,ok,我们这里先走流程,先看decodeFromSouce()方法:

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

    再进入到decodeFromSource()方法进入到DecodeJob类里:

    public Resource<Z> decodeFromSource() throws Exception {
            Resource<T> decoded = decodeSource();
            return transformEncodeAndTranscode(decoded);
        }
    
    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;
        }
    
    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;
        }
    

    因为简书文章限度问题,接下来的就只能分篇写了。。。
    下文链接:http://www.jianshu.com/p/8104be187f10

    我的微信公共账号,不定期更新干货,欢迎关注

    相关文章

      网友评论

        本文标题:Glide加载图片流程源码解析(1)

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