Glide加载图片流程源码解析

来源:互联网 发布:软件专业论文题目 编辑:程序博客网 时间:2024/06/07 23:35

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

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

主要的功能列表示意图

先来看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()应该在这个里面:

@Override    public DataFetcher<ImageVideoWrapper> getResourceFetcher(A model, int width, int height) {        DataFetcher<InputStream> streamFetcher = null;        if (streamLoader != null) {            streamFetcher = streamLoader.getResourceFetcher(model, width, height);        }        DataFetcher<ParcelFileDescriptor> fileDescriptorFetcher = null;        if (fileDescriptorLoader != null) {            fileDescriptorFetcher = fileDescriptorLoader.getResourceFetcher(model, width, height);        }        if (streamFetcher != null || fileDescriptorFetcher != null) {            return new ImageVideoFetcher(streamFetcher, fileDescriptorFetcher);        } else {            return null;        }    }

因为我们现在是第一次调用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;    }

在这里,我们看到了fetcher.loadData()方法,这里的fetcher其实就是httpUrlFetcher的实体对象,接着往下看:

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

哦?我们终于看到了跟网络通讯有关的东西了。在这里,我们只是拿到了一个inputStream的输入流而已。ok,我们再回去,回到DecodeJob的decodeSource()方法,我们发现这个方法其实起到了解码的作用:

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

这里的loadProvider当然还是之前的FixdLoadProvider,它的sourceDecoder其实就是ImageVideoGifDrawableLoadProvider里的sourceDecoder,也就是GifBitmapWrapperResourceDecoder的一个对象,我们顺着这条路,来看GifBitmapWrapperResourceDecoder这个类的decode()方法:

private GifBitmapWrapper decode(ImageVideoWrapper source, int width, int height, byte[] bytes) throws IOException {        final GifBitmapWrapper result;        if (source.getStream() != null) {            result = decodeStream(source, width, height, bytes);        } else {            result = decodeBitmapWrapper(source, width, height);        }        return result;    }private GifBitmapWrapper decodeStream(ImageVideoWrapper source, int width, int height, byte[] bytes)            throws IOException {        InputStream bis = streamFactory.build(source.getStream(), bytes);        bis.mark(MARK_LIMIT_BYTES);        ImageHeaderParser.ImageType type = parser.parse(bis);        bis.reset();        GifBitmapWrapper result = null;        if (type == ImageHeaderParser.ImageType.GIF) {            result = decodeGifWrapper(bis, width, height);        }        // Decoding the gif may fail even if the type matches.        if (result == null) {            // We can only reset the buffered InputStream, so to start from the beginning of the stream, we need to            // pass in a new source containing the buffered stream rather than the original stream.            ImageVideoWrapper forBitmapDecoder = new ImageVideoWrapper(bis, source.getFileDescriptor());            result = decodeBitmapWrapper(forBitmapDecoder, width, height);        }        return result;    }

我们看到,这里通过调用decodeStream()方法来读取数据,根据ImageHeaderParser.ImageType来判断这张图到底是gif图还是普通图片,gif图的解码过程我看了半天其实还没搞清楚,有点复杂,等我搞清楚了再来,我们这里先看静图的解码过程吧

private GifBitmapWrapper decodeBitmapWrapper(ImageVideoWrapper toDecode, int width, int height) throws IOException {        GifBitmapWrapper result = null;        Resource<Bitmap> bitmapResource = bitmapDecoder.decode(toDecode, width, height);        if (bitmapResource != null) {            result = new GifBitmapWrapper(bitmapResource, null);        }        return result;    }

这里调用了一个bitmapDecoder.decode(toDecode, width, height)方法,这其实就是ImageVideoBitmapDecoder的decode()方法

 public Resource<Bitmap> decode(ImageVideoWrapper source, int width, int height) throws IOException {        Resource<Bitmap> result = null;        InputStream is = source.getStream();        if (is != null) {            try {                result = streamDecoder.decode(is, width, height);            } catch (IOException e) {                if (Log.isLoggable(TAG, Log.VERBOSE)) {                    Log.v(TAG, "Failed to load image from stream, trying FileDescriptor", e);                }            }        }        if (result == null) {            ParcelFileDescriptor fileDescriptor = source.getFileDescriptor();            if (fileDescriptor != null) {                result = fileDescriptorDecoder.decode(fileDescriptor, width, height);            }        }        return result;    }

我们看到这里又是调用了streamDecoder.decode(is, width, height);的方法,定位一下其实streamDecoder就是StreamBitmapDecoder类,ok,继续:

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

oh shit,终于看到bitmap了,ok,来看decode()方法:

 @Override    public Bitmap decode(InputStream is, BitmapPool pool, int outWidth, int outHeight, DecodeFormat decodeFormat) {        final ByteArrayPool byteArrayPool = ByteArrayPool.get();        final byte[] bytesForOptions = byteArrayPool.getBytes();        final byte[] bytesForStream = byteArrayPool.getBytes();        final BitmapFactory.Options options = getDefaultOptions();        // Use to fix the mark limit to avoid allocating buffers that fit entire images.        RecyclableBufferedInputStream bufferedStream = new RecyclableBufferedInputStream(                is, bytesForStream);        // Use to retrieve exceptions thrown while reading.        // TODO(#126): when the framework no longer returns partially decoded Bitmaps or provides a way to determine        // if a Bitmap is partially decoded, consider removing.        ExceptionCatchingInputStream exceptionStream =                ExceptionCatchingInputStream.obtain(bufferedStream);        // Use to read data.        // Ensures that we can always reset after reading an image header so that we can still attempt to decode the        // full image even when the header decode fails and/or overflows our read buffer. See #283.        MarkEnforcingInputStream invalidatingStream = new MarkEnforcingInputStream(exceptionStream);        try {            exceptionStream.mark(MARK_POSITION);            int orientation = 0;            try {                orientation = new ImageHeaderParser(exceptionStream).getOrientation();            } catch (IOException e) {                if (Log.isLoggable(TAG, Log.WARN)) {                    Log.w(TAG, "Cannot determine the image orientation from header", e);                }            } finally {                try {                    exceptionStream.reset();                } catch (IOException e) {                    if (Log.isLoggable(TAG, Log.WARN)) {                        Log.w(TAG, "Cannot reset the input stream", e);                    }                }            }            options.inTempStorage = bytesForOptions;            final int[] inDimens = getDimensions(invalidatingStream, bufferedStream, options);            final int inWidth = inDimens[0];            final int inHeight = inDimens[1];            final int degreesToRotate = TransformationUtils.getExifOrientationDegrees(orientation);            final int sampleSize = getRoundedSampleSize(degreesToRotate, inWidth, inHeight, outWidth, outHeight);            final Bitmap downsampled =                    downsampleWithSize(invalidatingStream, bufferedStream, options, pool, inWidth, inHeight, sampleSize,                            decodeFormat);            // BitmapFactory swallows exceptions during decodes and in some cases when inBitmap is non null, may catch            // and log a stack trace but still return a non null bitmap. To avoid displaying partially decoded bitmaps,            // we catch exceptions reading from the stream in our ExceptionCatchingInputStream and throw them here.            final Exception streamException = exceptionStream.getException();            if (streamException != null) {                throw new RuntimeException(streamException);            }            Bitmap rotated = null;            if (downsampled != null) {                rotated = TransformationUtils.rotateImageExif(downsampled, pool, orientation);                if (!downsampled.equals(rotated) && !pool.put(downsampled)) {                    downsampled.recycle();                }            }            return rotated;        } finally {            byteArrayPool.releaseBytes(bytesForOptions);            byteArrayPool.releaseBytes(bytesForStream);            exceptionStream.release();            releaseOptions(options);        }    }

在这里,我们对服务器返回的inputStream进行了读取,以及图片的加载, MarkEnforcingInputStream invalidatingStream = new MarkEnforcingInputStream(exceptionStream)这个就是用来读取数据的。这个方法里还操作了很多逻辑,旋转,圆角等,具体就不详述了。ok,这里我们得到了bitmap对象,接下来任务就是就是把bitmap对象去显示出来。我们再次回到GifBitmapWrapperResourceDecoder的decodeBitmapWrapper方法中我们发现这里对bitmap进行了一次封装,同时支持了bitmap图片和gif图片,返回的是GifBitmapWrapper类的对象。ok知道了这个以后我们再回去,回到DecodeJob的decodeFromSource()方法:

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

再来看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;    }

这里前面的代码都没什么用,我们来看一开始transformed是一个Resource对象,经过transcode()方法之后变成了一个Resource对象,其实这里的transformed就是GifBitmapWrapper转变后的GifBitmapWrapper对象。我们再来看transcode()方法:

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

ok,再定位,这里的transcoder其实就是GifBitmapWrapperDrawableTranscoder的一个实例,接下去看它的transcode()方法:

@SuppressWarnings("unchecked")    @Override    public Resource<GlideDrawable> transcode(Resource<GifBitmapWrapper> toTranscode) {        GifBitmapWrapper gifBitmap = toTranscode.get();        Resource<Bitmap> bitmapResource = gifBitmap.getBitmapResource();        final Resource<? extends GlideDrawable> result;        if (bitmapResource != null) {            result = bitmapDrawableResourceTranscoder.transcode(bitmapResource);        } else {            result = gifBitmap.getGifResource();        }        // This is unchecked but always safe, anything that extends a Drawable can be safely cast to a Drawable.        return (Resource<GlideDrawable>) result;    }

这里transcode()方法直接返回了Resource。ok,接下来,时间回滚,我们又要回去了,回到EngineRunnable的decodeFromSource()方法,刚才的这么多分析,我们最终知道了decode()方法执行以后得到一个Resource对象。接下来就是如何显示的问题了,一个是错误的时候onLoadFailed(),还有一个就是加载完成以后调用的onLoadComplete(resource);方法,我们看里面return了onResourceReady(resource)方法,定位到EngineJob的onResourceReady()方法:

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

这里用到了handler,说明之前的EngineRunnable都是在子线程中加载的,handler通知MSG_COMPLETE,然后我们看到了:

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

感觉胜利在望了,已经又回到了主线程来更新UI了,接着来看 job.handleResultOnMainThread()方法:

private void handleResultOnMainThread() {        if (isCancelled) {            resource.recycle();            return;        } else if (cbs.isEmpty()) {            throw new IllegalStateException("Received a resource without any callbacks to notify");        }        engineResource = engineResourceFactory.build(resource, isCacheable);        hasResource = true;        // Hold on to resource for duration of request so we don't recycle it in the middle of notifying if it        // synchronously released by one of the callbacks.        engineResource.acquire();        listener.onEngineJobComplete(key, engineResource);        for (ResourceCallback cb : cbs) {            if (!isInIgnoredCallbacks(cb)) {                engineResource.acquire();                cb.onResourceReady(engineResource);            }        }        // Our request is complete, so we can release the resource.        engineResource.release();    }

这里发现调用了两遍onResouceReady(),ok,我们沿着方法的调用顺序回去,回到GenericRequest的onResourceReady()方法:

public void onResourceReady(Resource<?> resource) {        if (resource == null) {            onException(new Exception("Expected to receive a Resource<R> with an object of " + transcodeClass                    + " inside, but instead got null."));            return;        }        Object received = resource.get();        if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {            releaseResource(resource);            onException(new Exception("Expected to receive an object of " + transcodeClass                    + " but instead got " + (received != null ? received.getClass() : "") + "{" + received + "}"                    + " inside Resource{" + resource + "}."                    + (received != null ? "" : " "                        + "To indicate failure return a null Resource object, "                        + "rather than a Resource object containing null data.")            ));            return;        }        if (!canSetResource()) {            releaseResource(resource);            // We can't set the status to complete before asking canSetResource().            status = Status.COMPLETE;            return;        }        onResourceReady(resource, (R) received);    }private void onResourceReady(Resource<?> resource, R result) {        // We must call isFirstReadyResource before setting status.        boolean isFirstResource = isFirstReadyResource();        status = Status.COMPLETE;        this.resource = resource;        if (requestListener == null || !requestListener.onResourceReady(result, model, target, loadedFromMemoryCache,                isFirstResource)) {            GlideAnimation<R> animation = animationFactory.build(loadedFromMemoryCache, isFirstResource);            target.onResourceReady(result, animation);        }        notifyLoadSuccess();        if (Log.isLoggable(TAG, Log.VERBOSE)) {            logV("Resource ready in " + LogTime.getElapsedMillis(startTime) + " size: "                    + (resource.getSize() * TO_MEGABYTE) + " fromCache: " + loadedFromMemoryCache);        }    }

这里有两个onResourceReady()方法,第一个取得了封装的图片对象,然后传给了第二个onResouceReady()方法,注意这里有一个:
target.onResourceReady(result, animation);

定位这个target,发现其实就是GlideDrawableImageViewTarget的实例,来看这个类:

public class GlideDrawableImageViewTarget extends ImageViewTarget<GlideDrawable> {    private static final float SQUARE_RATIO_MARGIN = 0.05f;    private int maxLoopCount;    private GlideDrawable resource;    public GlideDrawableImageViewTarget(ImageView view) {        this(view, GlideDrawable.LOOP_FOREVER);    }    public GlideDrawableImageViewTarget(ImageView view, int maxLoopCount) {        super(view);        this.maxLoopCount = maxLoopCount;    }    @Override    public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {        if (!resource.isAnimated()) {            float viewRatio = view.getWidth() / (float) view.getHeight();            float drawableRatio = resource.getIntrinsicWidth() / (float) resource.getIntrinsicHeight();            if (Math.abs(viewRatio - 1f) <= SQUARE_RATIO_MARGIN                    && Math.abs(drawableRatio - 1f) <= SQUARE_RATIO_MARGIN) {                resource = new SquaringDrawable(resource, view.getWidth());            }        }        super.onResourceReady(resource, animation);        this.resource = resource;        resource.setLoopCount(maxLoopCount);        resource.start();    }    /**     * Sets the drawable on the view using     * {@link android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}.     *     * @param resource The {@link android.graphics.drawable.Drawable} to display in the view.     */    @Override    protected void setResource(GlideDrawable resource) {        view.setImageDrawable(resource);    }    @Override    public void onStart() {        if (resource != null) {            resource.start();        }    }    @Override    public void onStop() {        if (resource != null) {            resource.stop();        }    }}

注意这里的onSourceReady()方法,super.onResourceReady(resource, animation);
我们来到它的父类ImageViewTarget类:

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

这是个抽象方法,所以我们去子类寻找实现的逻辑,也就是GlideDrawableImageViewTarget类:

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

酷哦。到这里也就显示出来了。

厉害了,写了这么多,本来想把Glide的缓存一并讲进去了,但实在太长了,算了,另起一篇了只能。接下去会写一篇Glide的缓存机制,Fresco源码解析(都说Fresco性能上比Glide要优秀,但是到底优秀在哪里。我觉得有必要深究一下)。

阅读全文
0 0
原创粉丝点击