天天看点

Android进阶——源码分析之图片加载框架Glide

前言

源码阅读不是一件简单的事情,每次都要花费很长时间来梳理其内部的原理,所以有朋友觉得看一遍看不懂,那很正常,接下来就是考验你耐心的时候。学习源码的目的是:学习它好的地方,吸收起来作为我们项目的开发。作为你想进阶成跟别人有优势的程序员,那么阅读代码是你的基本功,懂得提取别人优秀的代码,进行修改成为你的代码,那就是你牛逼的地方,所以还是静下心来看看源代码吧。当然,阅读代码也不要做到只见树木,不见森林

Glide主要特点

  • 支持Memory和Disk图片缓存
  • 支持gif和webp格式图片
  • 根据Activity/Fragment自动管理其生命周期
  • 使用Bitmap Pool可以使Bitmap复用
  • 对于回收的Bitmap会主动调用recycle,减小系统回收压力

Glide的分析流程

Glide图片加载只需要简单的一句链式调用即可高效的加载我们的图片,那么其源码的分析流程也是通过以下的三个方法进行分析

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

Glide的with源码分析

一、with源码中实现原理

我们可以通过with的源码看出,with重载方法很多,可以兼容Activity、Fragment、Application等,这里我们主要以Activity来分析,其他的源码分析大同小异,其with方法实现的主要原理如下

Android进阶——源码分析之图片加载框架Glide

二、with源码中涉及到的类

  • RequestManagerRetriever:是关联Activity与RequestManager的使者类
  • RequestManager:是管理和启动Glide的请求类
  • RequestManagerFragment:是一个Fragment
  • ActivityFragmentLifecycle:生命周期接口

三、with源码分析

with源码所做的事情

  • 将传进来的Activity和RequestManager关联起来
  • 将Activity的生命周期和RequestManager的生命周期关联起来

with是如何实现Activity和RequestManager关联起来的?首先进入with源码,按追踪步数阅读

public static RequestManager with(Context context) {
    //第一步:拿到RequestManagerRetriever单例
    RequestManagerRetriever retriever = RequestManagerRetriever.get();
    //第二步:通过RequestManagerRetriever拿到RequestManager,追踪下去 
    return retriever.get(context);
}

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) {
            //第三步:根据传进来不同的参数,进行对应的方法去获得RequestManager,追踪下去
            return get((Activity) context);
        } else if (context instanceof ContextWrapper) {
            return get(((ContextWrapper) context).getBaseContext());
        }
    }

    return getApplicationManager(context);
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public RequestManager get(Activity activity) {
    if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
        //这里是做线程的判断和和版本的兼容
        return get(activity.getApplicationContext());
    } else {
        //断言:Activity是否被销毁
        assertNotDestroyed(activity);
        //获取Activity中的FragmentManager,为后面将隐藏的Fragment依附于Activity上做准备,这里不做分析
        android.app.FragmentManager fm = activity.getFragmentManager();
        //第四步:根据传进的Activity和FragmentManager,进行对应的方法去获得RequestManager,追踪下去
        return fragmentGet(activity, fm);
    }
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
    //获取隐藏的Fragment
    RequestManagerFragment current = getRequestManagerFragment(fm);
    //获取当前RequestManager 
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
        //第五步:如果为空则创建出新的RequestManager,将Activity和生命周期作为参数传递进去
        //那么这样子就关联起了Activity与RequestManager
        requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
        //设置当前RequestManager 
        current.setRequestManager(requestManager);
    }
    return requestManager;
}
           

其实上面连贯起来是非常简单的一段代码,那么它们是如何将Activity的生命周期和RequestManager的生命周期关联起来的?我们刚才也分析过,其生命周期的传递过程是由Activity->Fragment->RequestManager,那么这样的一个传递过程是如何实现的呢?

首先当Activity生命周期发生改变时,就会在Fragment中调用相应的方法,我们上面有看到通过getRequestManagerFragment方法,来获取Fragment的,追踪其代码

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) {
    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
        current = pendingRequestManagerFragments.get(fm);
        if (current == null) {
            //它是在这里直接创建出新的Fragment,追踪下去
            current = new RequestManagerFragment();
            pendingRequestManagerFragments.put(fm, current);
            fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
            handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
        }
    }
    return current;
}
           

来到RequestManagerFragment

public class RequestManagerFragment extends Fragment {
    private final ActivityFragmentLifecycle lifecycle;

    public RequestManagerFragment() {
        //调用自身的构造方法,追踪下去
        this(new ActivityFragmentLifecycle());
    }

    // For testing only.
    @SuppressLint("ValidFragment")
    RequestManagerFragment(ActivityFragmentLifecycle lifecycle) {
        //赋值
        this.lifecycle = lifecycle;
    }

    //根据Activity传进来的不同生命周期方法,调用自身lifecycle的回调方法
    //我们上面也知道,这个lifecycle已经传递给了RequestManager
    //那么它就会回调RequestManager中对应的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();
    }
}
           

目前,生命周期的回调方法已经从Fragment传到RequestManager类中的lifecycle回调,我们上面也分析到创建出新的RequestManager中时,我们进入这个构造方法,看看具体做了什么事情

public class RequestManager implements LifecycleListener {

    private final Lifecycle lifecycle;

    public RequestManager(Context context, Lifecycle lifecycle, RequestManagerTreeNode treeNode) {
        //第一步:调用自身的构造方法,追踪下去
        this(context, lifecycle, treeNode, new RequestTracker(), new ConnectivityMonitorFactory());
    }

    RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,
            RequestTracker requestTracker, ConnectivityMonitorFactory factory) {
        //参数的赋值,将Fragment中的lifecycle传递进来
        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 (Util.isOnBackgroundThread()) {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    //第二步:设置lifecycle的接口回调
                    lifecycle.addListener(RequestManager.this);
                }
            });
        } else {
            //第二步:设置lifecycle的接口回调
            lifecycle.addListener(this);
        }
        lifecycle.addListener(connectivityMonitor);
    }

    ......

    //第三步:由于RequestManager已经实现了LifecycleListener,也设置好了lifecycle的接口回调
    //那么当有接口方法回调的时候,就会执行对应的方法,也就是Activity发生变化通知Fragment,Fragment通知到这里来
    @Override
    public void onStart() {
        //第四步:根据不同的生命周期,执行不同的Glide请求,这里就不继续分析下去
        resumeRequests();
    }

    @Override
    public void onStop() {
        pauseRequests();
    }

    @Override
    public void onDestroy() {
        requestTracker.clearRequests();
    }
}
           

那么上面涉及到的LifecycleListener,其实就是生命周期的回调接口

public interface LifecycleListener {
    void onStart();
    void onStop();
    void onDestroy();
}
           

Glide的load源码分析

一、load源码分析

load方法主要是创建DrawableTypeRequest,并将记录相关的uri等数据供后续使用,按追踪步数阅读

public DrawableTypeRequest<String> load(String string) {
    //第一步:记录有关对应的参数,最终转成DrawableTypeRequest
    return (DrawableTypeRequest<String>) fromString().load(string);
}
public DrawableTypeRequest<String> fromString() {
    return loadGeneric(String.class);
}
public DrawableTypeRequest<Uri> load(Uri uri) {
    return (DrawableTypeRequest<Uri>) fromUri().load(uri);
}
public DrawableTypeRequest<Uri> fromUri() {
    return loadGeneric(Uri.class);
}
public DrawableTypeRequest<File> load(File file) {
    return (DrawableTypeRequest<File>) fromFile().load(file);
}
public DrawableTypeRequest<File> fromFile() {
    return loadGeneric(File.class);
}
public DrawableTypeRequest<Integer> load(Integer resourceId) {
    return (DrawableTypeRequest<Integer>) fromResource().load(resourceId);
}
public DrawableTypeRequest<Integer> fromResource() {
    return (DrawableTypeRequest<Integer>) loadGeneric(Integer.class)
            .signature(ApplicationVersionSignature.obtain(context));
}
public DrawableTypeRequest<URL> load(URL url) {
    return (DrawableTypeRequest<URL>) fromUrl().load(url);
}
public DrawableTypeRequest<URL> fromUrl() {
    return loadGeneric(URL.class);
}
           

load过程分为两步操作

  • fromString():创建DrawableTypeRequest
  • load():返回当前GenericRequestBuilder

1、追踪fromString()

public DrawableTypeRequest<String> fromString() {
    //第二步:调用loadGeneric方法
    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(
            //第三步:创建DrawableTypeRequest,这里追踪下去其实就是一堆参数的赋值,所以没必要再看了
            new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
                    glide, requestTracker, lifecycle, optionsApplier));
}
           

2、追踪load()

load采用的是构造者模式,返回GenericRequestBuilder构造者,返回这个类可以构造出图片加载的其他属性,比如:缩略图thumbnail(0.1f)、跳过内存缓存skipMemoryCache(true)、等属性

@Override
public DrawableRequestBuilder<ModelType> load(ModelType model) {
    //追踪父类实现方式
    super.load(model);
    return this;
}

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

Glide的into源码分析

一、into源码分析

into方法主要是使用多线程来加载图片,从into方法开始,按追踪步数阅读

@Override
public Target<GlideDrawable> into(ImageView view) {
    //第一步:调用父类into方法,追踪下去
    return super.into(view);
}

public Target<TranscodeType> into(ImageView view) {
    //判断当前线程,只有主线程才能继续执行
    Util.assertMainThread();
    if (view == null) {
        throw new IllegalArgumentException("You must pass in a non null View");
    }
    //如果没有设置过transform()或centerCrop,那么以ImageView的scaleType属性为准
    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.
        }
    }
    //第二步:这里分为两步
    //glide.buildImageViewTarget:创建由Glide自己抽象出来的Target(即泛型的View)
    //into:构建请求
    return into(glide.buildImageViewTarget(view, transcodeClass));
}
           

buildImageViewTarget其实就是将我们传进去的View,再封装成Glide抽象的泛型View,它会根据当前传入的clazz参数返回相应的类

<R> Target<R> buildImageViewTarget(ImageView imageView, Class<R> transcodedClass) {
    //追踪下去
    return imageViewTargetFactory.buildTarget(imageView, transcodedClass);
}

/**
 * 根据当前传入的clazz参数返回相应的Target类
 */
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)");
    }
}
           

我们回到第二步into方法,在这个方法中,主要会构建出一个Request对象,并执行这个Request对象

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对象
    Request previous = target.getRequest();
    //如果Request存在则回收
    if (previous != null) {
        previous.clear();
        requestTracker.removeRequest(previous);
        previous.recycle();
    }
    //第三步:重新构建出一个Request对象
    Request request = buildRequest(target);
    target.setRequest(request);
    lifecycle.addListener(target);
    //第四步:交给Request追踪器继续执行request
    requestTracker.runRequest(request);

    return target;
}
           

我们从第三步开始看起,这里分成三种情况,但最终都会调用obtainRequest,而obtainRequest追踪下去只是对Request的初始化而已

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

/*
 * 根据不同的逻辑判断构建出不同的Request,前面的分支都是跟缩略图有关的处理
 */
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.
        //最终还是调用obtainRequest,追踪下去
        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);
}

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")
    //这里会去对应的Request池找到是否有复用的Request
    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的初始化
    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;
}
           

我们从第四步开始看起,runRequest,这里是真正执行的地方。可以看到如果没有处于暂停状态,会直接调用request.begein(),如果处于暂停状态,那么先添加到队列中,等恢复到正常状态时,会再调用request.begin()。即无论如何都会调用request.begin()

public void runRequest(Request request) {
    requests.add(request);
    //当前是否正在请求
    if (!isPaused) {
         //第五步:如果没有请求,则开始请求,追踪下去
        request.begin();
    } else {
        //如果有请求,则添加到挂起请求中去
        pendingRequests.add(request);
    }
}

public void begin() {
    startTime = LogTime.getLogTime();
    if (model == null) {
        onException(null);
        return;
    }

    status = Status.WAITING_FOR_SIZE;
    if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
        //第六步:如果用户设置了Override的方法,那么就会去确定图片的宽高,追踪下去
        onSizeReady(overrideWidth, overrideHeight);
    } else {
        //如果没有设置宽高,则会去测量宽高,最终还是会走到onSizeReady方法中
        target.getSize(this);
    }
    //先加载我们默认的图片
    if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
        target.onLoadStarted(getPlaceholderDrawable());
    }
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
        logV("finished run method in " + LogTime.getElapsedMillis(startTime));
    }
}

@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:负责从数据源中获取原始数据
    ModelLoader<A, T> modelLoader = loadProvider.getModelLoader();
    //DataFetcher:负责将图片来源转换成我们需要的图片数据
    final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height);

    if (dataFetcher == null) {
        onException(new Exception("Failed to load model: \'" + model + "\'"));
        return;
    }
    //ResourceTranscoder:负责将我们的IO流解码成Bitmap等
    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));
    }
}
           

engine其实就是个Engine类,它是负责启动负载和管理活动和缓存资源。engine.load这个方法中分为两步,第一步处理缓存,第二步真正执行加载, 构建出EngineJob,执行EngineRunnable

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();
    //key是用来存储缓存的唯一标识
    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);
}
           

EngineRunnable其实就是个Runnable,通过其start方法最终会调用run方法,追踪到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);
    }
}

private void onLoadComplete(Resource resource) {
    //追踪下去
    manager.onResourceReady(resource);
}

@Override
public void onResourceReady(final Resource<?> resource) {
    this.resource = resource;
    //第十步:通过Handler发送消息,加载图片资源
    MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
}
           

总结

其实Glide的源码解析还有很多东西,大概的流程如下面这张图,后面具体的分析可以看个人兴趣去阅读

Android进阶——源码分析之图片加载框架Glide