深入解析Glide源码

来源:互联网 发布:网络暴力的案例 编辑:程序博客网 时间:2024/05/14 17:51

Glide 是 Google的开源项目, Glide具有获取、解码和展示视频剧照、图片、动画等功能,它还有灵活的API,这些API使开发者能够将Glide应用在几乎任何网络协议栈里。创建Glide的主要目的有两个,一个是实现平滑的图片列表滚动效果,另一个是支持远程图片的获取、大小调整和展示。本篇博客,我们一起深入分析Glide的源码。

总体设计

这里写图片描述

with方法

首先我们来看一下glide的一般使用方法

Glide.with(this)        .load("http://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=%E5%9B%BE%E7%89%87&hs=0&pn=0&spn=0&di=157484237350&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&ie=utf-8&oe=utf-8&cl=2&lm=-1&cs=4271053251%2C2424464488&os=2375022793%2C1835605452&simid=4247939438%2C550168575&adpicid=0&lpn=0&ln=30&fr=ala&fm=&sme=&cg=&bdtype=0&oriquery=&objurl=http%3A%2F%2Fpic55.nipic.com%2Ffile%2F20141208%2F19462408_171130083000_2.jpg&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3Bgtrtv_z%26e3Bv54AzdH3Fzi7wgptAzdH3F8c8n9d9_d_z%26e3Bip4s&gsm=0")        .into(mImageView);

with方法主要就是用于创建RequestManager,这里是Glide通过Activity/Fragment生命周期管理Request原理所在,流程图如下:
这里写图片描述

那我们就从with方法入手,with方法传入的参数可以是Context,Activity,Fragment或FragmentActiviy,以FragmentActiviy为例子

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

获取了RequestManagerRetriever,并调用了其get方法

public RequestManager get(FragmentActivity activity) {    if (Util.isOnBackgroundThread()) {        return get(activity.getApplicationContext());    } else {        assertNotDestroyed(activity);        FragmentManager fm = activity.getSupportFragmentManager();        return supportFragmentGet(activity, fm);    }}

判断是否在主线程中调用,如果是子线程中,则调用get(activity.getApplicationContext())

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

很明显传入的context是ApplicationContext,所以会调用getApplicationManager(context)

private RequestManager getApplicationManager(Context context) {    // Either an application context or we're on a background thread.    if (applicationManager == null) {        synchronized (this) {            if (applicationManager == null) {                // Normally pause/resume is taken care of by the fragment we add to the fragment or activity.                // However, in this case since the manager attached to the application will not receive lifecycle                // events, we must force the manager to start resumed using ApplicationLifecycle.                applicationManager = new RequestManager(context.getApplicationContext(),                        new ApplicationLifecycle(), new EmptyRequestManagerTreeNode());            }        }    }    return applicationManager;}

创建了一个RequestManager,并将其返回,这里的ApplicationLifecycle很重要,下面会提到,再回到之前的get方法

public RequestManager get(FragmentActivity activity) {    if (Util.isOnBackgroundThread()) {        return get(activity.getApplicationContext());    } else {        assertNotDestroyed(activity);        FragmentManager fm = activity.getSupportFragmentManager();        return supportFragmentGet(activity, fm);    }}

如果在主线程中调用get方法,则会通过获取传入activity的FragmentManager,并将其传入到supportFragmentGet(activity, fm);方法中

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

首先是调用getSupportRequestManagerFragment方法获取一个SupportRequestManagerFragment,SupportRequestManagerFragment 是一个无界面的Fragment类,起到把请求和Activity生命周期同步的作用。

SupportRequestManagerFragment getSupportRequestManagerFragment(final FragmentManager fm) {    SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(        FRAGMENT_TAG);    if (current == null) {        current = pendingSupportRequestManagerFragments.get(fm);        if (current == null) {            current = new SupportRequestManagerFragment();            pendingSupportRequestManagerFragments.put(fm, current);            fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();            handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();        }    }    return current;}

可以看到 getSupportRequestManagerFragment中,会先去判断传入的FragmentManager 中是否已经绑定了这个SupportRequestManagerFragment ,没有就将其创建,并添加到FragmentManager 中

我们可以看到SupportRequestManagerFragment 中,生命周期的方法,都会同步调用lifecycle的相应方法

@Overridepublic void onStart() {    super.onStart();    lifecycle.onStart();}@Overridepublic void onStop() {    super.onStop();    lifecycle.onStop();}

而这个lifecycle就是ActivityFragmentLifecycle,它将用了观察者模式,可以发现addListener就是添加观察者,然后每一个生命周期方法,同步通知给每一个listener

@Overridepublic void addListener(LifecycleListener listener) {    lifecycleListeners.add(listener);    if (isDestroyed) {        listener.onDestroy();    } else if (isStarted) {        listener.onStart();    } else {        listener.onStop();    }}void onStart() {    isStarted = true;    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {        lifecycleListener.onStart();    }}

回到supportFragmentGet方法中

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

接下来就是获取SupportRequestManagerFragment 中的RequestManager,判断其是否存在,不在则进行创建,然后和SupportRequestManagerFragment 进行绑定,这里需要强调的是,构建RequestManager时,将SupportRequestManagerFragment 的lifecycle传入,我们看看RequestManager的构造函数里面

RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,        RequestTracker requestTracker, ConnectivityMonitorFactory factory) {    this.context = context.getApplicationContext();    this.lifecycle = lifecycle;    this.treeNode = treeNode;    this.requestTracker = requestTracker;    this.glide = Glide.get(context);    this.optionsApplier = new OptionsApplier();    ConnectivityMonitor connectivityMonitor = factory.build(context,            new RequestManagerConnectivityListener(requestTracker));    // If we're the application level request manager, we may be created on a background thread. In that case we    // cannot risk synchronously pausing or resuming requests, so we hack around the issue by delaying adding    // ourselves as a lifecycle listener by posting to the main thread. This should be entirely safe.    if (Util.isOnBackgroundThread()) {        new Handler(Looper.getMainLooper()).post(new Runnable() {            @Override            public void run() {                lifecycle.addListener(RequestManager.this);            }        });    } else {        lifecycle.addListener(this);    }    lifecycle.addListener(connectivityMonitor);}

可以发现,lifecycle.addListener方法,将RequestManager自身添加到lifecycle中,这里的巧妙之处,在于,SupportRequestManagerFragment 的生命周期的方法,都会同步通知lifecycle的所有Listener,所以SupportRequestManagerFragment 的生命周期都可同步通知RequestManager,这就是glide的巧妙之处。

上面还做了判断,如果这个RequestManager是application级别的,将其post到主线程中,再调用 lifecycle.addListener(RequestManager.this);方法,保证生命周期的同步效果

到这里,with方法的逻辑就执行完毕了,那么总结一下这个方法的作用,通过with方法中的参数不同,调用RequestManagerRetriever的get方法,最终创建一个空的Fragment 名为SupportRequestManagerFragment 并绑定一个RequestManager

load方法

with方法返回的是一个RequestManager,那么load方法的逻辑显然就是在RequestManager中

load调用处理流程图:
这里写图片描述

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

会先调用fromString再调用load方法

public DrawableTypeRequest<String> fromString() {    return loadGeneric(String.class);}
private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) {    ModelLoader<T, InputStream> streamModelLoader = Glide.buildStreamModelLoader(modelClass, context);    ModelLoader<T, ParcelFileDescriptor> fileDescriptorModelLoader =            Glide.buildFileDescriptorModelLoader(modelClass, context);    if (modelClass != null && streamModelLoader == null && fileDescriptorModelLoader == null) {        throw new IllegalArgumentException("Unknown type " + modelClass + ". You must provide a Model of a type for"                + " which there is a registered ModelLoader, if you are using a custom model, you must first call"                + " Glide#register with a ModelLoaderFactory for your custom model class");    }    return optionsApplier.apply(            new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,                    glide, requestTracker, lifecycle, optionsApplier));}

loadGeneric方法中创建了两个ModelLoader,分别是streamModelLoader 和fileDescriptorModelLoader,然后通过他们构造了一个DrawableTypeRequest

其实就是通过工厂模式创建相应的类型的ModelLoader,我们以Glide.buildStreamModelLoader为例

public static <T> ModelLoader<T, InputStream> buildStreamModelLoader(Class<T> modelClass, Context context) {    return buildModelLoader(modelClass, InputStream.class, context);}

这里传递了InputStream.class

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

通过Glide.get(context).getLoaderFactory()获取GenericLoaderFactory并调用其buildModelLoader创建InputStream.class对应的ModelLoader

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

getCachedLoader方法判断InputStream.class对应的ModelLoader是否已经创建过,也就是是否存在内存缓存中,有则返回

然后调用了getFactory方法,根据InputStream.class,创建其对应的ModelLoaderFactory

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()) {            // This accounts for model subclasses, our map only works for exact matches. We should however still            // match a subclass of a model with a factory for a super class of that model if if there isn't a            // factory for that particular subclass. Uris are a great example of when this happens, most uris            // are actually subclasses for Uri, but we'd generally rather load them all with the same factory rather            // than trying to register for each subclass individually.            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;}

可以发现ModelLoaderFactory是保存在一个叫resourceToFactories的Map 中,而这个Map又是存储在名叫modelClassToResourceFactories的Map 中

然后是调用ModelLoaderFactory的build方法创建ModelLoader,然后通过cacheModelLoader方法将ModelLoader进行缓存起来

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

fromString的流程就分析完毕,然后回到RequestManager的load方法

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

fromString返回DrawableTypeRequest,所以load方法在DrawableTypeRequest中

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

只是对我们传进来的图片的uri进行赋值

Into方法

into方法是加载图片的发起点,其逻辑在DrawableRequestBuilder类中

public Target<GlideDrawable> into(ImageView view) {    return super.into(view);}

调用了GenericRequestBuilder的into方法

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

根据不同的ImageView 的ScaleType有不同的处理逻辑,applyCenterCrop()方法和 applyFitCenter()的实现都是在子类DrawableRequestBuilder中

public DrawableRequestBuilder<ModelType> fitCenter() {    return transform(glide.getDrawableFitCenter());}

然后调用了transform方法

public DrawableRequestBuilder<ModelType> transform(Transformation<GifBitmapWrapper>... transformation) {    super.transform(transformation);    return this;}
public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> transform(        Transformation<ResourceType>... transformations) {    isTransformationSet = true;    if (transformations.length == 1) {        transformation = transformations[0];    } else {        transformation = new MultiTransformation<ResourceType>(transformations);    }    return this;}

其实就是对GenericRequestBuilder中的transformation 进行赋值,而这个transformation 是通过glide.getDrawableFitCenter()方法进行赋值

GifBitmapWrapperTransformation getDrawableFitCenter() {    return drawableFitCenter;}

而这个drawableFitCenter是在Glide的构造函数中进行赋值的

bitmapFitCenter = new FitCenter(bitmapPool);drawableFitCenter = new GifBitmapWrapperTransformation(bitmapPool, bitmapFitCenter);

FitCenter是BitmapTransformation的子类,BitmapTransformation 实现了Transformation

接下来看一下GifBitmapWrapperTransformation的创建过程

public GifBitmapWrapperTransformation(BitmapPool bitmapPool, Transformation<Bitmap> bitmapTransformation) {    this(bitmapTransformation, new GifDrawableTransformation(bitmapTransformation, bitmapPool));}

传入了FitCenter和BitmapPool (此类很重要,后面会讲解),里面又创建了GifDrawableTransformation来包裹这两个参数

GifBitmapWrapperTransformation(Transformation<Bitmap> bitmapTransformation,        Transformation<GifDrawable> gifDataTransformation) {    this.bitmapTransformation = bitmapTransformation;    this.gifDataTransformation = gifDataTransformation;}

然后调用了glide.buildImageViewTarget(view, transcodeClass)

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

这里的transcodedClass传入的是 GlideDrawable

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

根据clazz的类型不同,构建不同的ImageViewTarget

public GlideDrawableImageViewTarget(ImageView view) {    this(view, GlideDrawable.LOOP_FOREVER);}public GlideDrawableImageViewTarget(ImageView view, int maxLoopCount) {    super(view);    this.maxLoopCount = maxLoopCount;}

无论哪种类型的ImageViewTarget都调用了父类ImageViewTarget的构造方法

public ImageViewTarget(ImageView view) {    super(view);}public ViewTarget(T view) {    if (view == null) {        throw new NullPointerException("View must not be null!");    }    this.view = view;    sizeDeterminer = new SizeDeterminer(view);}public SizeDeterminer(View view) {    this.view = view;}

然后这个GlideDrawableImageViewTarget会被传入到into方法中

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

判断之前针对这个imageView创建的GlideDrawableImageViewTarget是否已经创建了Request ,如果已经存在则进行清空,并从requestTracker中移除,如果之前从创建过,就首先调用buildRequest方法创建Request

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

这里有Request 优先级的设置

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

进入到obtain方法中

GenericRequest<A, T, Z, R> request = (GenericRequest<A, T, Z, R>) REQUEST_POOL.poll();if (request == null) {    request = new GenericRequest<A, T, Z, R>();}request.init(loadProvider,        model,        signature,        context,        priority,        target,        sizeMultiplier,        placeholderDrawable,        placeholderResourceId,        errorDrawable,        errorResourceId,        fallbackDrawable,        fallbackResourceId,        requestListener,        requestCoordinator,        engine,        transformation,        transcodeClass,        isMemoryCacheable,        animationFactory,        overrideWidth,        overrideHeight,        diskCacheStrategy);return request;

首先从REQUEST_POOL这个队列中拿出一个request,如果不存在,则新建一个,request的构造函数是空实现,其相关参数是在其init方法进行初始化的

{    this.loadProvider = loadProvider;    this.model = model;    this.signature = signature;    this.fallbackDrawable = fallbackDrawable;    this.fallbackResourceId = fallbackResourceId;    this.context = context.getApplicationContext();    this.priority = priority;    this.target = target;    this.sizeMultiplier = sizeMultiplier;    this.placeholderDrawable = placeholderDrawable;    this.placeholderResourceId = placeholderResourceId;    this.errorDrawable = errorDrawable;    this.errorResourceId = errorResourceId;    this.requestListener = requestListener;    this.requestCoordinator = requestCoordinator;    this.engine = engine;    this.transformation = transformation;    this.transcodeClass = transcodeClass;    this.isMemoryCacheable = isMemoryCacheable;    this.animationFactory = animationFactory;    this.overrideWidth = overrideWidth;    this.overrideHeight = overrideHeight;    this.diskCacheStrategy = diskCacheStrategy;    status = Status.PENDING;    // We allow null models by just setting an error drawable. Null models will always have empty providers, we    // simply skip our sanity checks in that unusual case.    if (model != null) {        check("ModelLoader", loadProvider.getModelLoader(), "try .using(ModelLoader)");        check("Transcoder", loadProvider.getTranscoder(), "try .as*(Class).transcode(ResourceTranscoder)");        check("Transformation", transformation, "try .transform(UnitTransformation.get())");        if (diskCacheStrategy.cacheSource()) {            check("SourceEncoder", loadProvider.getSourceEncoder(),                    "try .sourceEncoder(Encoder) or .diskCacheStrategy(NONE/RESULT)");        } else {            check("SourceDecoder", loadProvider.getSourceDecoder(),                    "try .decoder/.imageDecoder/.videoDecoder(ResourceDecoder) or .diskCacheStrategy(ALL/SOURCE)");        }        if (diskCacheStrategy.cacheSource() || diskCacheStrategy.cacheResult()) {            // TODO if(resourceClass.isAssignableFrom(InputStream.class) it is possible to wrap sourceDecoder            // and use it instead of cacheDecoder: new FileToStreamDecoder<Z>(sourceDecoder)            // in that case this shouldn't throw            check("CacheDecoder", loadProvider.getCacheDecoder(),                    "try .cacheDecoder(ResouceDecoder) or .diskCacheStrategy(NONE)");        }        if (diskCacheStrategy.cacheResult()) {            check("Encoder", loadProvider.getEncoder(),                    "try .encode(ResourceEncoder) or .diskCacheStrategy(NONE/SOURCE)");        }    }}

对request进行赋值,然后各种check校验,根据DiskCacheStrategy中策略的不同,一共4种策略,默认DiskCacheStrategy的策略是RESULT

public enum DiskCacheStrategy {    /** Caches with both {@link #SOURCE} and {@link #RESULT}. */    ALL(true, true),    /** Saves no data to cache. */    NONE(false, false),    /** Saves just the original data to cache. */    SOURCE(true, false),    /** Saves the media item after all transformations to cache. */    RESULT(false, true);    private final boolean cacheSource;    private final boolean cacheResult;    DiskCacheStrategy(boolean cacheSource, boolean cacheResult) {        this.cacheSource = cacheSource;        this.cacheResult = cacheResult;    }    /**     * Returns true if this request should cache the original unmodified data.     */    public boolean cacheSource() {        return cacheSource;    }    /**     * Returns true if this request should cache the final transformed result.     */    public boolean cacheResult() {        return cacheResult;    }}

回到GenericRequestBuilder 的into方法中

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

将这个request 设置进GlideDrawableImageViewTarget中

public void setRequest(Request request) {    setTag(request);}private void setTag(Object tag) {    if (tagId == null) {        isTagUsedAtLeastOnce = true;        view.setTag(tag);    } else {        view.setTag(tagId, tag);    }}

其实就是将imageView和request 通过setTag方法进行绑定

然后将GlideDrawableImageViewTarget添加到lifecycle中,接着调用requestTracker.runRequest(request),执行这个request

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

首先将request添加到requests中

private final Set<Request> requests = Collections.newSetFromMap(new WeakHashMap<Request, Boolean>());

然后执行request的begin方法

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

onSizeReady方法中调用了Engine的load方法,首先创建了一个EngineKey

EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),        loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),        transcoder, loadProvider.getSourceEncoder());

通过这个key去查找缓存是否存在

EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {    if (!isMemoryCacheable) {        return null;    }    EngineResource<?> cached = getEngineResourceFromCache(key);    if (cached != null) {        cached.acquire();        activeResources.put(key, new ResourceWeakReference(key, cached, getReferenceQueue()));    }    return cached;}

通过getEngineResourceFromCache方法获取EngineResource

private EngineResource<?> getEngineResourceFromCache(Key key) {    Resource<?> cached = cache.remove(key);    final EngineResource result;    if (cached == null) {        result = null;    } else if (cached instanceof EngineResource) {        // Save an object allocation if we've cached an EngineResource (the typical case).        result = (EngineResource) cached;    } else {        result = new EngineResource(cached, true /*isCacheable*/);    }    return result;}

先从cache中寻找资源,如果找到则将其从cache中移除并放入activeResources中,,activeResources是一个Map

if (cached != null) {    cb.onResourceReady(cached);    if (Log.isLoggable(TAG, Log.VERBOSE)) {        logWithTimeAndKey("Loaded resource from cache", startTime, key);    }    return null;}

然后如果资源在缓存中找到后会放入cb.onResourceReady(cached)进行回调,cb是ResourceCallback

如果loadFromCache找不到则调用loadFromActiveResources

private EngineResource<?> loadFromActiveResources(Key key, boolean isMemoryCacheable) {    if (!isMemoryCacheable) {        return null;    }    EngineResource<?> active = null;    WeakReference<EngineResource<?>> activeRef = activeResources.get(key);    if (activeRef != null) {        active = activeRef.get();        if (active != null) {            active.acquire();        } else {            activeResources.remove(key);        }    }    return active;}

其实就是从activeResources中获取EngineResource,如果能获取到EngineResource,则放入cb.onResourceReady进行回调

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

cache是LruResourceCache对象,作为资源的LRU缓存;activeResources是以弱引用为值的Map,用于缓存使用中的资源。比一般内存缓存额外多一级缓存的意义在于,当内存不足时清理cache中的资源时,不会对使用中的Bitmap造成影响。

以上两个缓存中都找不到的话,就会从jobs通过key获取EngineJob,如果EngineJob存在的话,则用其构造LoadStatus进行返回

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对象并调用其start方法,同时也创建了DecodeJob,将EngineJob和DecodeJob构造一个EngineRunnable

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的start方法执行EngineRunnable

public void start(EngineRunnable engineRunnable) {    this.engineRunnable = engineRunnable;    future = diskCacheService.submit(engineRunnable);}

diskCacheService的类型是ThreadPoolExecutor的子类FifoPriorityThreadPoolExecutor,也就是说将engineRunnable放入线程池中执行。

然后自然会执行到EngineRunnable的run方法

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

在EngineRunnable的run方法中进行编码,执行decode方法

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

根据缓存策略调用decodeFromCache或者decodeFromSource

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

先看decodeFromSource,调用DecodeJob的decodeFromSource方法。

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

先看decodeSource里面的逻辑

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

先通过DataFetcher访问网络获得文件流,接口DataFetcher的实现类根据配置而不同,我们看看HttpUrlFetcher的loadData方法的实现

@Overridepublic InputStream loadData(Priority priority) throws Exception {    return loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/, glideUrl.getHeaders());}

其实内部就是建立网络链接,获取InputStream

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 传入decodeFromSourceData方法中

private Resource<T> cacheAndDecodeSourceData(A data) throws IOException {    long startTime = LogTime.getLogTime();    SourceWriter<A> writer = new SourceWriter<A>(loadProvider.getSourceEncoder(), data);    diskCacheProvider.getDiskCache().put(resultKey.getOriginalKey(), writer);    if (Log.isLoggable(TAG, Log.VERBOSE)) {        logWithTimeAndKey("Wrote source to cache", startTime);    }    startTime = LogTime.getLogTime();    Resource<T> result = loadFromCache(resultKey.getOriginalKey());    if (Log.isLoggable(TAG, Log.VERBOSE) && result != null) {        logWithTimeAndKey("Decoded source from cache", startTime);    }    return result;}

先将SourceWriter放入diskCacheProvider的DiskCache中,然后调用loadFromCache

private Resource<T> loadFromCache(Key key) throws IOException {    File cacheFile = diskCacheProvider.getDiskCache().get(key);    if (cacheFile == null) {        return null;    }    Resource<T> result = null;    try {        result = loadProvider.getCacheDecoder().decode(cacheFile, width, height);    } finally {        if (result == null) {            diskCacheProvider.getDiskCache().delete(key);        }    }    return result;}

根据需要将文件流写入磁盘缓存,再对文件流进行编码

public Resource<Bitmap> decode(InputStream source, int width, int height) {    Bitmap bitmap = downsampler.decode(source, bitmapPool, width, height, decodeFormat);    return BitmapResource.obtain(bitmap, bitmapPool);}
ublic 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);    }}

编码过程中通过设置采样率缩放图片,降低内存占用,提高加载性能。

private Bitmap downsampleWithSize(MarkEnforcingInputStream is, RecyclableBufferedInputStream  bufferedStream,        BitmapFactory.Options options, BitmapPool pool, int inWidth, int inHeight, int sampleSize,        DecodeFormat decodeFormat) {    // Prior to KitKat, the inBitmap size must exactly match the size of the bitmap we're decoding.    Bitmap.Config config = getConfig(is, decodeFormat);    options.inSampleSize = sampleSize;    options.inPreferredConfig = config;    if ((options.inSampleSize == 1 || Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT) && shouldUsePool(is)) {        int targetWidth = (int) Math.ceil(inWidth / (double) sampleSize);        int targetHeight = (int) Math.ceil(inHeight / (double) sampleSize);        // BitmapFactory will clear out the Bitmap before writing to it, so getDirty is safe.        setInBitmap(options, pool.getDirty(targetWidth, targetHeight, config));    }    return decodeStream(is, bufferedStream, options);}
private static Bitmap decodeStream(MarkEnforcingInputStream is, RecyclableBufferedInputStream bufferedStream,        BitmapFactory.Options options) {     if (options.inJustDecodeBounds) {         // This is large, but jpeg headers are not size bounded so we need something large enough to minimize         // the possibility of not being able to fit enough of the header in the buffer to get the image size so         // that we don't fail to load images. The BufferedInputStream will create a new buffer of 2x the         // original size each time we use up the buffer space without passing the mark so this is a maximum         // bound on the buffer size, not a default. Most of the time we won't go past our pre-allocated 16kb.         is.mark(MARK_POSITION);     } else {         // Once we've read the image header, we no longer need to allow the buffer to expand in size. To avoid         // unnecessary allocations reading image data, we fix the mark limit so that it is no larger than our         // current buffer size here. See issue #225.         bufferedStream.fixMarkLimit();     }    final Bitmap result = BitmapFactory.decodeStream(is, null, options);    try {        if (options.inJustDecodeBounds) {            is.reset();        }    } catch (IOException e) {        if (Log.isLoggable(TAG, Log.ERROR)) {            Log.e(TAG, "Exception loading inDecodeBounds=" + options.inJustDecodeBounds                    + " sample=" + options.inSampleSize, e);        }    }    return result;}

这样返回的InpuStream就通过downsampleWithSize方法变为了Bitmap,如果设置了degreesToRotate(旋转的角度),就调用rotateImageExif设置

Bitmap rotated = null;if (downsampled != null) {    rotated = TransformationUtils.rotateImageExif(downsampled, pool, orientation);    if (!downsampled.equals(rotated) && !pool.put(downsampled)) {        downsampled.recycle();    }}
public static Bitmap rotateImageExif(Bitmap toOrient, BitmapPool pool, int exifOrientation) {    final Matrix matrix = new Matrix();    initializeMatrixForRotation(exifOrientation, matrix);    if (matrix.isIdentity()) {        return toOrient;    }    // From Bitmap.createBitmap.    final RectF newRect = new RectF(0, 0, toOrient.getWidth(), toOrient.getHeight());    matrix.mapRect(newRect);    final int newWidth = Math.round(newRect.width());    final int newHeight = Math.round(newRect.height());    Bitmap.Config config = getSafeConfig(toOrient);    Bitmap result = pool.get(newWidth, newHeight, config);    if (result == null) {        result = Bitmap.createBitmap(newWidth, newHeight, config);    }    matrix.postTranslate(-newRect.left, -newRect.top);    final Canvas canvas = new Canvas(result);    final Paint paint = new Paint(PAINT_FLAGS);    canvas.drawBitmap(toOrient, matrix, paint);    return result;}

回到decodeFromSource方法

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

transform方法调用了Transformation的transform方法

private Resource<T> transform(Resource<T> decoded) {    if (decoded == null) {        return null;    }    Resource<T> transformed = transformation.transform(decoded, width, height);    if (!decoded.equals(transformed)) {        decoded.recycle();    }    return transformed;}

Transformation是接口;BitmapTransformation实现了该接口但留下了另一个抽象方法transform;CenterCrop和FitCenter两个类继承了BitmapTransformation并实现了抽象方法transform。

public final Resource<Bitmap> transform(Resource<Bitmap> resource, int outWidth, int outHeight) {    if (!Util.isValidDimensions(outWidth, outHeight)) {        throw new IllegalArgumentException("Cannot apply transformation on width: " + outWidth + " or height: "                + outHeight + " less than or equal to zero and not Target.SIZE_ORIGINAL");    }    Bitmap toTransform = resource.get();    int targetWidth = outWidth == Target.SIZE_ORIGINAL ? toTransform.getWidth() : outWidth;    int targetHeight = outHeight == Target.SIZE_ORIGINAL ? toTransform.getHeight() : outHeight;    Bitmap transformed = transform(bitmapPool, toTransform, targetWidth, targetHeight);    final Resource<Bitmap> result;    if (toTransform.equals(transformed)) {        result = resource;    } else {        result = BitmapResource.obtain(transformed, bitmapPool);    }    return result;}

接下来看一下CenterCrop的transform方法

protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {    final Bitmap toReuse = pool.get(outWidth, outHeight, toTransform.getConfig() != null            ? toTransform.getConfig() : Bitmap.Config.ARGB_8888);    Bitmap transformed = TransformationUtils.centerCrop(toReuse, toTransform, outWidth, outHeight);    if (toReuse != null && toReuse != transformed && !pool.put(toReuse)) {        toReuse.recycle();    }    return transformed;}

由BitmapPool提供一个Bitmap作为下一步的Canvas载体。BitmapPool的实现类是LruBitmapPool,顾名思义是一个基于LRU方式的Bitmap缓存池,用于Bitmap的复用。

接下来是TransformationUtils的centerCrop方法

public static Bitmap centerCrop(Bitmap recycled, Bitmap toCrop, int width, int height) {    if (toCrop == null) {        return null;    } else if (toCrop.getWidth() == width && toCrop.getHeight() == height) {        return toCrop;    }    // From ImageView/Bitmap.createScaledBitmap.    final float scale;    float dx = 0, dy = 0;    Matrix m = new Matrix();    if (toCrop.getWidth() * height > width * toCrop.getHeight()) {        scale = (float) height / (float) toCrop.getHeight();        dx = (width - toCrop.getWidth() * scale) * 0.5f;    } else {        scale = (float) width / (float) toCrop.getWidth();        dy = (height - toCrop.getHeight() * scale) * 0.5f;    }    m.setScale(scale, scale);    m.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));    final Bitmap result;    if (recycled != null) {        result = recycled;    } else {        result = Bitmap.createBitmap(width, height, getSafeConfig(toCrop));    }    // We don't add or remove alpha, so keep the alpha setting of the Bitmap we were given.    TransformationUtils.setAlpha(toCrop, result);    Canvas canvas = new Canvas(result);    Paint paint = new Paint(PAINT_FLAGS);    canvas.drawBitmap(toCrop, m, paint);    return result;}

在TransformationUtils的centerCrop方法中,根据目标尺寸调整矩阵并绘制结果。

FitCenter类的逻辑与centerCrop类相似,回到DecodeJob的transformEncodeAndTranscode方法
接下来调用writeTransformedToCache将转换结果写入磁盘缓存,

private void writeTransformedToCache(Resource<T> transformed) {    if (transformed == null || !diskCacheStrategy.cacheResult()) {        return;    }    long startTime = LogTime.getLogTime();    SourceWriter<Resource<T>> writer = new SourceWriter<Resource<T>>(loadProvider.getEncoder(), transformed);    diskCacheProvider.getDiskCache().put(resultKey, writer);    if (Log.isLoggable(TAG, Log.VERBOSE)) {        logWithTimeAndKey("Wrote transformed from source to cache", startTime);    }}

再调用transcode方法进行转码

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

transcode方法中的transcoder的实际类型是GlideBitmapDrawableTranscoder

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

GlideBitmapDrawableTranscoder的transcode方法将Bitmap资源进行封装

public GlideBitmapDrawableResource(GlideBitmapDrawable drawable, BitmapPool bitmapPool) {    super(drawable);    this.bitmapPool = bitmapPool;}

到这里就结束了decodeFromSource的流程。

接下来看decodeFromCache

private Resource<?> decodeFromCache() throws Exception {    Resource<?> result = null;    try {        result = decodeJob.decodeResultFromCache();    } catch (Exception e) {        if (Log.isLoggable(TAG, Log.DEBUG)) {            Log.d(TAG, "Exception decoding result from cache: " + e);        }    }    if (result == null) {        result = decodeJob.decodeSourceFromCache();    }    return result;}

先调用DecodeJob的decodeResultFromCache方法获取,获取失败则调用DecodeJob的decodeSourceFromCache方法

public Resource<Z> decodeResultFromCache() throws Exception {    if (!diskCacheStrategy.cacheResult()) {        return null;    }    long startTime = LogTime.getLogTime();    Resource<T> transformed = loadFromCache(resultKey);    if (Log.isLoggable(TAG, Log.VERBOSE)) {        logWithTimeAndKey("Decoded transformed from cache", startTime);    }    startTime = LogTime.getLogTime();    Resource<Z> result = transcode(transformed);    if (Log.isLoggable(TAG, Log.VERBOSE)) {        logWithTimeAndKey("Transcoded transformed from cache", startTime);    }    return result;}

decodeResultFromCache方法从磁盘缓存中获取对应Bitmap并将其转码

public Resource<Z> decodeSourceFromCache() throws Exception {    if (!diskCacheStrategy.cacheSource()) {        return null;    }    long startTime = LogTime.getLogTime();    Resource<T> decoded = loadFromCache(resultKey.getOriginalKey());    if (Log.isLoggable(TAG, Log.VERBOSE)) {        logWithTimeAndKey("Decoded source from cache", startTime);    }    return transformEncodeAndTranscode(decoded);}

decodeSourceFromCache方法从磁盘缓存中获取对应Bitmap并将其转换(因为是原尺寸,需要调整大小)

EngineRunnable的decode是decodeFromCache和decodeFromSource二选一,decodeFromCache也获取失败的话会怎么样呢?

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

缓存中没有结果的情况下会调用onLoadFailed方法

private void onLoadFailed(Exception e) {    if (isDecodingFromCache()) {        stage = Stage.SOURCE;        manager.submitForSource(this);    } else {        manager.onException(e);    }}public void submitForSource(EngineRunnable runnable) {    future = sourceService.submit(runnable);}

变更缓存策略重新放入线程池中执行,也就是从网络获取。这里的线程池是sourceService而不是上面的diskCacheService,

得到了处理结果,接下来调用EngineRunnable的onLoadComplete方法将结果传入

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

onLoadComplete方法调用了EngineJob的onResourceReady方法

public void onResourceReady(final Resource<?> resource) {    this.resource = resource;    MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();}
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;    }}

关键在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();}

onResourceReady方法中向Handler传递消息并由MainThreadCallback处理消息 ,也就切换到了主线程。handleResultOnMainThread方法会调用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方法调用GlideDrawableImageViewTarget的onResourceReady方法

public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {    if (!resource.isAnimated()) {        //TODO: Try to generalize this to other sizes/shapes.        // This is a dirty hack that tries to make loading square thumbnails and then square full images less costly        // by forcing both the smaller thumb and the larger version to have exactly the same intrinsic dimensions.        // If a drawable is replaced in an ImageView by another drawable with different intrinsic dimensions,        // the ImageView requests a layout. Scrolling rapidly while replacing thumbs with larger images triggers        // lots of these calls and causes significant amounts of jank.        float viewRatio = view.getWidth() / (float) view.getHeight();        float drawableRatio = resource.getIntrinsicWidth() / (float) resource.getIntrinsicHeight();        if (Math.abs(viewRatio - 1f) <= SQUARE_RATIO_MARGIN                && Math.abs(drawableRatio - 1f) <= SQUARE_RATIO_MARGIN) {            resource = new SquaringDrawable(resource, view.getWidth());        }    }    super.onResourceReady(resource, animation);    this.resource = resource;    resource.setLoopCount(maxLoopCount);    resource.start();}

GlideDrawableImageViewTarget的onResourceReady方法调用其父类ImageViewTarget的onResourceReady方法

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

ImageViewTarget的onResourceReady方法中调用的抽象方法setResource在子类GlideDrawableImageViewTarget中实现,该方法中调用了ImageView的setImageDrawable方法设置图像。至此,整个加载流程就完成了。

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

最后简单归纳一下整个加载流程的图
这里写图片描述