Android图片加载框架最新解析:从源码的角度理解Glide的执行流程


众所周知Glide是Android开发中普遍使用的图片加载框架,功能非常强大,API非常简便,也是Google官方唯一推荐的图片加载框架。
基本用法,本文不再叙述,详情请参阅 官方Github主页
一般情况下,我们想在界面上显示一张图片,只需要一行代码即可实现。图下所示:

Glide.with(this).load(url).into(imageView)

看起来是如此的简洁、完美!但你可能不知道Glide在背后做了多么复杂、繁重的工作,才将图片展示到我们面前。本着知其然也要知其所以然,那么今天我们就来揭开Glide神秘的面纱。

准备源码

既然要阅读源码,必须先要把源码下载下来,下载有两种方式:
第一种(推荐):如果项目中已经用到Glide,那么就可以用Android Studio 打开项目,点击Glide的引用直接查看。
第二种:在Glide的Github开源主页下载源码,地址:https://github.com/bumptech/glide
这里推荐第一种,因为使用Android Studio阅读可以进行自由的跳转,方便我们阅读。本文是基于最新的Glide 4.11.0来解析的,随着官方不停的版本迭代,本文也会随着变动不定时更新。读者也可以在下方留言反馈。

开始阅读

问:如何把大象装冰箱里?
答:总共分三步,第一步,Glide.with(this);第二步,load(url);第三步,into(imageView)。
阅读源码的思路是从我们平时使用的语句开始,也就是Glide.with(this)。
在分析的过程中我们不必把源码的每一句都搞懂,那样会把你搞得晕头转向,摸不清思路。因为这些代码都不是一个人写的,同样的功能有多种解决方法。记住我们只需要分析主要的实现逻辑就可以了。
准备好了吗?现在我们开始!

1、with()

with()方法是Glide类中的一组静态方法,有多个重载方法,如下所示:

public class Glide implements ComponentCallbacks2 {
	...
	
	@NonNull
  public static RequestManager with(@NonNull Context context) {
    return getRetriever(context).get(context);
  }
  
  @NonNull
  public static RequestManager with(@NonNull Activity activity) {
    return getRetriever(activity).get(activity);
  }
  
  @NonNull
  public static RequestManager with(@NonNull FragmentActivity activity) {
    return getRetriever(activity).get(activity);
  }
  
  @NonNull
  public static RequestManager with(@NonNull Fragment fragment) {
    return getRetriever(fragment.getContext()).get(fragment);
  }
  
  @SuppressWarnings("deprecation")
  @Deprecated
  @NonNull
  public static RequestManager with(@NonNull android.app.Fragment fragment) {
    return getRetriever(fragment.getActivity()).get(fragment);
  }
  
  @NonNull
  public static RequestManager with(@NonNull View view) {
    return getRetriever(view.getContext()).get(view);
  }
  ...
}

可以看到,with()的重载方法非常多,可以传入Context、Activity、Fragment以及View,其中传入android.app.Fragment的方法已经标记为过时,不建议使用了,我们可以传入androidx.fragment.app.Fragment来替代。 每个with()方法中的逻辑都非常简单,都先是调用getRetriever()静态方法传入Context对象获得一个RequestManagerRetriever对象,然后调用RequestManagerRetriever的get()方法获取RequestManager“请求管理器”对象。
先看下getRetriever()方法:

public class Glide implements ComponentCallbacks2 {
	...
	@NonNull
  private static RequestManagerRetriever getRetriever(@Nullable Context context) {
    // Context could be null for other reasons (ie the user passes in null), but in practice it will
    // only occur due to errors with the Fragment lifecycle.
    Preconditions.checkNotNull(
        context,
        "You cannot start a load on a not yet attached View or a Fragment where getActivity() "
            + "returns null (which usually occurs when getActivity() is called before the Fragment "
            + "is attached or after the Fragment is destroyed).");
    return Glide.get(context).getRequestManagerRetriever();
  }
  
  @NonNull
  public static Glide get(@NonNull Context context) {
    if (glide == null) {
      GeneratedAppGlideModule annotationGeneratedModule =
          getAnnotationGeneratedGlideModules(context.getApplicationContext());
      synchronized (Glide.class) {
        if (glide == null) {
          checkAndInitializeGlide(context, annotationGeneratedModule);
        }
      }
    }

    return glide;
  }
  
@NonNull
  public RequestManagerRetriever getRequestManagerRetriever() {
    return requestManagerRetriever;
  }
	...
}

通过get()方法中两次判断glide == null,再加上synchronized(),表明这里是一个单例模式,具体的单例细节我们不必深究。这里getRetriever()方法中调用get()方法获取Glide单例对象,然后通过Glide对象获取内部的RequestManagerRetriever对象,RequestManagerRetriever是Glide构造方法中定义的对象。
接下来我们看RequestManagerRetriever的get()方法:

public class RequestManagerRetriever implements Handler.Callback {
...
	@NonNull
  public RequestManager get(@NonNull 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
          && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
        return get(((ContextWrapper) context).getBaseContext());
      }
    }

    return getApplicationManager(context);
  }

  @NonNull
  public RequestManager get(@NonNull FragmentActivity activity) {
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(activity);
      FragmentManager fm = activity.getSupportFragmentManager();
      return supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }

  @NonNull
  public RequestManager get(@NonNull Fragment fragment) {
    Preconditions.checkNotNull(
        fragment.getContext(),
        "You cannot start a load on a fragment before it is attached or after it is destroyed");
    if (Util.isOnBackgroundThread()) {
      return get(fragment.getContext().getApplicationContext());
    } else {
      FragmentManager fm = fragment.getChildFragmentManager();
      return supportFragmentGet(fragment.getContext(), fm, fragment, fragment.isVisible());
    }
  }

  @SuppressWarnings("deprecation")
  @NonNull
  public RequestManager get(@NonNull Activity activity) {
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(activity);
      android.app.FragmentManager fm = activity.getFragmentManager();
      return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }

  @SuppressWarnings("deprecation")
  @NonNull
  public RequestManager get(@NonNull View view) {
    if (Util.isOnBackgroundThread()) {
      return get(view.getContext().getApplicationContext());
    }

    Preconditions.checkNotNull(view);
    Preconditions.checkNotNull(
        view.getContext(), "Unable to obtain a request manager for a view without a Context");
    Activity activity = findActivity(view.getContext());
    if (activity == null) {
      return get(view.getContext().getApplicationContext());
    }
    if (activity instanceof FragmentActivity) {
      Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
      return fragment != null ? get(fragment) : get((FragmentActivity) activity);
    }
    android.app.Fragment fragment = findFragment(view, activity);
    if (fragment == null) {
      return get(activity);
    }
    return get(fragment);
  }
...
}

上述代码有很多的get()重载方法,看起来比较复杂,其实梳理一下还是很简单的。不论传入的是Context,还是Fragment等等,实际上只有两种情况而已,即传入Application类型的情况和非Application的情况。
有一点需要说明,通过if (Util.isOnMainThread())判断语句,可以看出,我们如果在非主线程中使用Glide,它都会当成传入Application的情况来处理。

先来看传入Application类型的情况。如果在Glide.with()方法中传入Application对象,这里会调用get(context)中的getApplicationManager(context)方法。如下所示:

public class RequestManagerRetriever implements Handler.Callback {
...
@NonNull
  private RequestManager getApplicationManager(@NonNull Context context) {
    if (applicationManager == null) {
      synchronized (this) {
        if (applicationManager == null) {
          Glide glide = Glide.get(context.getApplicationContext());
          applicationManager =
              factory.build(
                  glide,
                  new ApplicationLifecycle(),
                  new EmptyRequestManagerTreeNode(),
                  context.getApplicationContext());
        }
      }
    }
    return applicationManager;
  }
...
}

由于Glide本身就是和应用程序生命周期同步的,所以这里并不需要做什么特殊处理。应用关闭,Glide加载也会终止。
上面的情况比较简单,我们再来看传非Application的情况。无论传Fragment还是Activity,最终的流程都是向当前的Activity添加一个隐藏的Fragment。使用这样一个小技巧,这样Glide就可以知道Activity的生命周期了,加载图片时,也会随着Activity的生命周期,判断是否继续加载。代码如下所示:

public class RequestManagerRetriever implements Handler.Callback {
...
@NonNull
  private RequestManager supportFragmentGet(
      @NonNull Context context,
      @NonNull FragmentManager fm,
      @Nullable Fragment parentHint,
      boolean isParentVisible) {
    SupportRequestManagerFragment current =
        getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      // TODO(b/27524013): Factor out this Glide.get() call.
      Glide glide = Glide.get(context);
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }
  
@NonNull
  private SupportRequestManagerFragment getSupportRequestManagerFragment(
      @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
    SupportRequestManagerFragment current =
        (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
      current = pendingSupportRequestManagerFragments.get(fm);
      if (current == null) {
        current = new SupportRequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        if (isParentVisible) {
          current.getGlideLifecycle().onStart();
        }
        pendingSupportRequestManagerFragments.put(fm, current);
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }
...
}

supportFragmentGet()中调用了getSupportRequestManagerFragment()方法,添加了一个SupportRequestManagerFragment ,SupportRequestManagerFragment 就是一个Fragment。

到这里,with()的源码比较好理解吧,不过越到后面会越复杂,接下来我们开始分析第二步吧!

2、load()

我们都知道Glide支持加载图片URL,或是本地路径等多种数据形式的,由于我们不可能把每种都分析一遍,所以这里只选其中之一加载图片URL的方法来研究。使用第一步with()返回的RequestManager对象调用load()方法,可以看出load()方法是在RequestManager类中,如下所示:

public class RequestManager
    implements ComponentCallbacks2, LifecycleListener, ModelTypes<RequestBuilder<Drawable>> {
...
@NonNull
  @CheckResult
  @Override
  public RequestBuilder<Drawable> load(@Nullable String string) {
    return asDrawable().load(string);
  }
  
  @NonNull
  @CheckResult
  public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
  }
  
  @NonNull
  @CheckResult
  public <ResourceType> RequestBuilder<ResourceType> as(
      @NonNull Class<ResourceType> resourceClass) {
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }
...
}

上述代码很简单,在load()方法中就是先创建一个RequestBuilder对象,再调用RequestBuilder中的load()方法。其实此类中的所有load重载方法逻辑都是调用RequestBuilder对象中load()方法,而且返回类型都是RequestBuilder。那为什么RequestBuilder类中还有很多load()重载方法呢?除了保存数据源,其实只是做了一点初始化配置上的不同而已。下面是RequestBuilder中的load()方法:

public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
    implements Cloneable, ModelTypes<RequestBuilder<TranscodeType>> {
...
@NonNull
  @Override
  @CheckResult
  public RequestBuilder<TranscodeType> load(@Nullable String string) {
    return loadGeneric(string);
  }
  
  @NonNull
  private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
    this.model = model;
    isModelSet = true;
    return this;
  }
...
}

至此,load()的逻辑就是这些,我们拿到RequestBuilder对象后,就可以调用apply()方法设置我们自定义的配置(RequestOptions对象),例如:placeholder(),error(),priority()等等。接下来我们看第三步into()中的逻辑。

3、into()

前面两步真是so easy!现在我们进入Glide加载流程中最复杂的部分看看吧。
代码如下:

public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
    implements Cloneable, ModelTypes<RequestBuilder<TranscodeType>> {
    ...
	@NonNull
  public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    Util.assertMainThread();
    Preconditions.checkNotNull(view);

    BaseRequestOptions<?> requestOptions = this;
    if (!requestOptions.isTransformationSet()
        && requestOptions.isTransformationAllowed()
        && view.getScaleType() != null) {
      switch (view.getScaleType()) {
        case CENTER_CROP:
          requestOptions = requestOptions.clone().optionalCenterCrop();
          break;
        case CENTER_INSIDE:
          requestOptions = requestOptions.clone().optionalCenterInside();
          break;
        case FIT_CENTER:
        case FIT_START:
        case FIT_END:
          requestOptions = requestOptions.clone().optionalFitCenter();
          break;
        case FIT_XY:
          requestOptions = requestOptions.clone().optionalCenterInside();
          break;
        case CENTER:
        case MATRIX:
        default:
          // Do nothing.
      }
    }

    return into(
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions,
        Executors.mainThreadExecutor());
  }
  ...
}

前面的一些判断逻辑是关于加载配置的,暂时不用管,我们先来看最后一行,调用glideContext.buildImageViewTarget()方法会构建一个Target对象,Target对象是来展示图片用的,我们跟进去代码如下:

public class GlideContext extends ContextWrapper {
...
@NonNull
  public <X> ViewTarget<ImageView, X> buildImageViewTarget(
      @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
    return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
  }
...
}

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

这里又调用了ImageViewTargetFactory类的buildTarget()方法,会根据传入的clazz参数判断是Bitmap就返回BitmapImageViewTarget对象,否则就返回DrawableImageViewTarget对象。至于clazz对象的由来,它是我们在调用asBitmap(),asGif()等方法时 传入的。现在回到into()方法,我们看到又调用了一个into()方法,代码如下:

public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
    implements Cloneable, ModelTypes<RequestBuilder<TranscodeType>> {
    ...
private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> options,
      Executor callbackExecutor) {
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

    Request request = buildRequest(target, targetListener, options, callbackExecutor);

    Request previous = target.getRequest();
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
      if (!Preconditions.checkNotNull(previous).isRunning()) {
        previous.begin();
      }
      return target;
    }

    requestManager.clear(target);
    target.setRequest(request);
    requestManager.track(target, request);

    return target;
  }
  ...
}

这些代码我们只抓核心,第14行buildRequest()构建Request对象,第27行requestManager.track()执行这个Request。
Request是一个非常关键的组件,是用来发出加载图片请求的。我们来看下它是如何构建的:

public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
    implements Cloneable, ModelTypes<RequestBuilder<TranscodeType>> {
    ...
    private Request buildRequest(
      Target<TranscodeType> target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> requestOptions,
      Executor callbackExecutor) {
    return buildRequestRecursive(
        /*requestLock=*/ new Object(),
        target,
        targetListener,
        /*parentCoordinator=*/ null,
        transitionOptions,
        requestOptions.getPriority(),
        requestOptions.getOverrideWidth(),
        requestOptions.getOverrideHeight(),
        requestOptions,
        callbackExecutor);
  }

  private Request buildRequestRecursive(
      Object requestLock,
      Target<TranscodeType> target,
      @Nullable RequestListener<TranscodeType> targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      BaseRequestOptions<?> requestOptions,
      Executor callbackExecutor) {

    // Build the ErrorRequestCoordinator first if necessary so we can update parentCoordinator.
    ErrorRequestCoordinator errorRequestCoordinator = null;
    if (errorBuilder != null) {
      errorRequestCoordinator = new ErrorRequestCoordinator(requestLock, parentCoordinator);
      parentCoordinator = errorRequestCoordinator;
    }

    Request mainRequest =
        buildThumbnailRequestRecursive(
            requestLock,
            target,
            targetListener,
            parentCoordinator,
            transitionOptions,
            priority,
            overrideWidth,
            overrideHeight,
            requestOptions,
            callbackExecutor);

    if (errorRequestCoordinator == null) {
      return mainRequest;
    }

    int errorOverrideWidth = errorBuilder.getOverrideWidth();
    int errorOverrideHeight = errorBuilder.getOverrideHeight();
    if (Util.isValidDimensions(overrideWidth, overrideHeight) && !errorBuilder.isValidOverride()) {
      errorOverrideWidth = requestOptions.getOverrideWidth();
      errorOverrideHeight = requestOptions.getOverrideHeight();
    }

    Request errorRequest =
        errorBuilder.buildRequestRecursive(
            requestLock,
            target,
            targetListener,
            errorRequestCoordinator,
            errorBuilder.transitionOptions,
            errorBuilder.getPriority(),
            errorOverrideWidth,
            errorOverrideHeight,
            errorBuilder,
            callbackExecutor);
    errorRequestCoordinator.setRequests(mainRequest, errorRequest);
    return errorRequestCoordinator;
  }
  
private Request obtainRequest(
      Object requestLock,
      Target<TranscodeType> target,
      RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> requestOptions,
      RequestCoordinator requestCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      Executor callbackExecutor) {
    return SingleRequest.obtain(
        context,
        glideContext,
        requestLock,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        glideContext.getEngine(),
        transitionOptions.getTransitionFactory(),
        callbackExecutor);
  }
    ...
}

这里又调用了buildRequestRecursive()方法,代码虽然长,大部分处理了缩略图的和出错的逻辑,主流程和缩略图逻辑在第42行buildThumbnailRequestRecursive()方法中,由于代码较多,这里梳理下,最终调用了第92行SingleRequest.obtain()返回的是一个SingleRequest对象,把加载图的所有配置参数都封装了进去,我们就不跟进去看了。
ok,现在构建了Request对象,那它是怎么执行的呢?回到刚才的into()方法,我们看下requestManager.track()方法:

public class RequestManager{
...
	synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
    targetTracker.track(target);
    requestTracker.runRequest(request);
  }
...
}

public class RequestTracker {
...
public void runRequest(@NonNull Request request) {
    requests.add(request);
    if (!isPaused) {
      request.begin();
    } else {
      request.clear();
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Paused, delaying request");
      }
      pendingRequests.add(request);
    }
  }
  ...
}

这里主要看track()中的requestTracker.runRequest()方法,这里的逻辑是先判断Glide当前是不是处理暂停状态,如果不是暂停状态就调用Request的begin()方法来执行Request,否则的话就先将Request添加到待执行队列里面,等暂停状态解除了之后再执行。
忽略掉暂停请求的功能,我们重点看下begin()方法。由于request实际上是一个SingleRequest对象,所以我们看下SingleRequest类中的begin()方法:

public final class SingleRequest<R> implements Request, SizeReadyCallback, ResourceCallback {
...
@Override
  public void begin() {
    synchronized (requestLock) {
      assertNotCallingCallbacks();
      stateVerifier.throwIfRecycled();
      startTime = LogTime.getLogTime();
      if (model == null) {
        if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
          width = overrideWidth;
          height = overrideHeight;
        }
        int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
        onLoadFailed(new GlideException("Received null model"), logLevel);
        return;
      }

      if (status == Status.RUNNING) {
        throw new IllegalArgumentException("Cannot restart a running request");
      }
      if (status == Status.COMPLETE) {
        onResourceReady(resource, DataSource.MEMORY_CACHE);
        return;
      }

      status = Status.WAITING_FOR_SIZE;
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
        onSizeReady(overrideWidth, overrideHeight);
      } else {
        target.getSize(this);
      }

      if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
          && canNotifyStatusChanged()) {
        target.onLoadStarted(getPlaceholderDrawable());
      }
      if (IS_VERBOSE_LOGGABLE) {
        logV("finished run method in " + LogTime.getElapsedMillis(startTime));
      }
    }
  }
  ...
}

这里有个细节注意一下,如果model == null,也就是我们传的图片URL地址为null,会走onLoadFailed()方法,设置占位图,具体逻辑感兴趣的可以去看下。我们说下正常情况,这里判断了你有没有使用override() API为图片指定固定宽高。如果指定了,就会执行第29行onSizeReady()方法。没指定,就会执行第31行target.getSize()方法。getSize()方法的内部会根据ImageView的layout_width和layout_height值计算出图片应该的宽高。在计算完之后,它也会调用onSizeReady()方法。那么我们看下onSizeReady()方法:

public final class SingleRequest<R> implements Request, SizeReadyCallback, ResourceCallback {
...
@Override
  public void onSizeReady(int width, int height) {
    stateVerifier.throwIfRecycled();
    synchronized (requestLock) {
      if (IS_VERBOSE_LOGGABLE) {
        logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
      }
      if (status != Status.WAITING_FOR_SIZE) {
        return;
      }
      status = Status.RUNNING;

      float sizeMultiplier = requestOptions.getSizeMultiplier();
      this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
      this.height = maybeApplySizeMultiplier(height, sizeMultiplier);

      if (IS_VERBOSE_LOGGABLE) {
        logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
      }
      loadStatus =
          engine.load(
              glideContext,
              model,
              requestOptions.getSignature(),
              this.width,
              this.height,
              requestOptions.getResourceClass(),
              transcodeClass,
              priority,
              requestOptions.getDiskCacheStrategy(),
              requestOptions.getTransformations(),
              requestOptions.isTransformationRequired(),
              requestOptions.isScaleOnlyOrNoTransform(),
              requestOptions.getOptions(),
              requestOptions.isMemoryCacheable(),
              requestOptions.getUseUnlimitedSourceGeneratorsPool(),
              requestOptions.getUseAnimationPool(),
              requestOptions.getOnlyRetrieveFromCache(),
              this,
              callbackExecutor);
      if (status != Status.RUNNING) {
        loadStatus = null;
      }
      if (IS_VERBOSE_LOGGABLE) {
        logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
      }
    }
  }
  ...
}

这里我们主要看onSizeReady()方法中的调用engine.load()方法:

public class Engine{
...
public <R> LoadStatus load(
      GlideContext glideContext,
      Object model,
      Key signature,
      int width,
      int height,
      Class<?> resourceClass,
      Class<R> transcodeClass,
      Priority priority,
      DiskCacheStrategy diskCacheStrategy,
      Map<Class<?>, Transformation<?>> transformations,
      boolean isTransformationRequired,
      boolean isScaleOnlyOrNoTransform,
      Options options,
      boolean isMemoryCacheable,
      boolean useUnlimitedSourceExecutorPool,
      boolean useAnimationPool,
      boolean onlyRetrieveFromCache,
      ResourceCallback cb,
      Executor callbackExecutor) {
    long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;

    EngineKey key =
        keyFactory.buildKey(
            model,
            signature,
            width,
            height,
            transformations,
            resourceClass,
            transcodeClass,
            options);

    EngineResource<?> memoryResource;
    synchronized (this) {
      memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);

      if (memoryResource == null) {
        return waitForExistingOrStartNewJob(
            glideContext,
            model,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            options,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache,
            cb,
            callbackExecutor,
            key,
            startTime);
      }
    }

    // Avoid calling back while holding the engine lock, doing so makes it easier for callers to
    // deadlock.
    cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
    return null;
  }

  private <R> LoadStatus waitForExistingOrStartNewJob(
      GlideContext glideContext,
      Object model,
      Key signature,
      int width,
      int height,
      Class<?> resourceClass,
      Class<R> transcodeClass,
      Priority priority,
      DiskCacheStrategy diskCacheStrategy,
      Map<Class<?>, Transformation<?>> transformations,
      boolean isTransformationRequired,
      boolean isScaleOnlyOrNoTransform,
      Options options,
      boolean isMemoryCacheable,
      boolean useUnlimitedSourceExecutorPool,
      boolean useAnimationPool,
      boolean onlyRetrieveFromCache,
      ResourceCallback cb,
      Executor callbackExecutor,
      EngineKey key,
      long startTime) {

    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
      current.addCallback(cb, callbackExecutor);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Added to existing load", startTime, key);
      }
      return new LoadStatus(cb, current);
    }

    EngineJob<R> engineJob =
        engineJobFactory.build(
            key,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache);

    DecodeJob<R> decodeJob =
        decodeJobFactory.build(
            glideContext,
            model,
            key,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            onlyRetrieveFromCache,
            options,
            engineJob);

    jobs.put(key, engineJob);

    engineJob.addCallback(cb, callbackExecutor);
    engineJob.start(decodeJob);

    if (VERBOSE_IS_LOGGABLE) {
      logWithTimeAndKey("Started new load", startTime, key);
    }
    return new LoadStatus(cb, engineJob);
  }
  ...
}

在load()方法中逻辑是先调用loadFromMemory()从内存获取数据,没有的话再调用waitForExistingOrStartNewJob()方法,关于缓存的逻辑,我们下一篇再学习,先从104行看起,这里构建了一个EngineJob,它的主要作用就是用来开启线程的,为后面的异步加载图片做准备。接着下面构建了DecodeJob对象,它看起来像是用来对图片进行解码的,但实际上它的任务十分繁重。DecodeJob就是一个Runnable对象,下面就调用了engineJob.start()方法,在子线程当中执行DecodeJob。我们来看看DecodeJob中的run()方法执行了什么?

class DecodeJob<R>
    implements DataFetcherGenerator.FetcherReadyCallback,
        Runnable,
        Comparable<DecodeJob<?>>,
        Poolable {
        ...
 @Override
  public void run() {
    GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)", model);
    DataFetcher<?> localFetcher = currentFetcher;
    try {
      if (isCancelled) {
        notifyFailed();
        return;
      }
      runWrapped();
    } catch (CallbackException e) {
      throw e;
    } catch (Throwable t) {
      if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(
            TAG,
            "DecodeJob threw unexpectedly" + ", isCancelled: " + isCancelled + ", stage: " + stage,
            t);
      }
      if (stage != Stage.ENCODE) {
        throwables.add(t);
        notifyFailed();
      }
      if (!isCancelled) {
        throw t;
      }
      throw t;
    } finally {
      if (localFetcher != null) {
        localFetcher.cleanup();
      }
      GlideTrace.endSection();
    }
  }
  
  private void runWrapped() {
    switch (runReason) {
      case INITIALIZE:
        stage = getNextStage(Stage.INITIALIZE);
        currentGenerator = getNextGenerator();
        runGenerators();
        break;
      case SWITCH_TO_SOURCE_SERVICE:
        runGenerators();
        break;
      case DECODE_DATA:
        decodeFromRetrievedData();
        break;
      default:
        throw new IllegalStateException("Unrecognized run reason: " + runReason);
    }
  }
  
  private Stage getNextStage(Stage current) {
    switch (current) {
      case INITIALIZE:
        return diskCacheStrategy.decodeCachedResource()
            ? Stage.RESOURCE_CACHE
            : getNextStage(Stage.RESOURCE_CACHE);
      case RESOURCE_CACHE:
        return diskCacheStrategy.decodeCachedData()
            ? Stage.DATA_CACHE
            : getNextStage(Stage.DATA_CACHE);
      case DATA_CACHE:
        // Skip loading from source if the user opted to only retrieve the resource from cache.
        return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
      case SOURCE:
      case FINISHED:
        return Stage.FINISHED;
      default:
        throw new IllegalArgumentException("Unrecognized stage: " + current);
    }
  }
  
  private DataFetcherGenerator getNextGenerator() {
    switch (stage) {
      case RESOURCE_CACHE:
        return new ResourceCacheGenerator(decodeHelper, this);
      case DATA_CACHE:
        return new DataCacheGenerator(decodeHelper, this);
      case SOURCE:
        return new SourceGenerator(decodeHelper, this);
      case FINISHED:
        return null;
      default:
        throw new IllegalStateException("Unrecognized stage: " + stage);
    }
  }
  ...
}

这里主要看run()中的runWrapped()方法,runWrapped()方法的逻辑是判断运行原因,在首次运行时runReason是初始值INITIALIZE,接下来调用getNextStage()获取下一步的状态,getNextStage()方法中会判断是否有缓存数据,具体的缓存逻辑暂不研究,我们先假设没有缓存,这时迭代此方法走RESOURCE_CACHE分支,我们再假设没有缓存,会迭代方法走DATA_CACHE分支,这里onlyRetrieveFromCache表示“仅从缓存里检索数据”,现在Glide还没找到数据,如果为true,流程就会结束,所以我们假设为false,返回Stage.SOURCE状态。然后getNextGenerator()方法,就会走SOURCE分支并返回SourceGenerator对象。我们要记住这时的currentGenerator值是一个SourceGenerator对象。因为下面我们要用到它,我们来看下runGenerators()方法:

class DecodeJob<R>{
...
private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    while (!isCancelled
        && currentGenerator != null
        && !(isStarted = currentGenerator.startNext())) {
      stage = getNextStage(stage);
      currentGenerator = getNextGenerator();

      if (stage == Stage.SOURCE) {
        reschedule();
        return;
      }
    }
    // We've run out of stages and generators, give up.
    if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
      notifyFailed();
    }
  }
  ...
}

这里比较绕,while循环里面的getNextStage(),getNextGenerator()我们已经分析过了,这里重点是看下第9行currentGenerator.startNext()方法。我们知道currentGenerator是一个SourceGenerator对象,所以startNext()方法在SourceGenerator类中,代码如下:

class SourceGenerator {
...
@Override
  public boolean startNext() {
    if (dataToCache != null) {
      Object data = dataToCache;
      dataToCache = null;
      cacheData(data);
    }

    if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
      return true;
    }
    sourceCacheGenerator = null;

    loadData = null;
    boolean started = false;
    while (!started && hasNextModelLoader()) {
      loadData = helper.getLoadData().get(loadDataListIndex++);
      if (loadData != null
          && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
              || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
        started = true;
        startNextLoad(loadData);
      }
    }
    return started;
  }

  private void startNextLoad(final LoadData<?> toStart) {
    loadData.fetcher.loadData(
        helper.getPriority(),
        new DataCallback<Object>() {
          @Override
          public void onDataReady(@Nullable Object data) {
            if (isCurrentRequest(toStart)) {
              onDataReadyInternal(toStart, data);
            }
          }

          @Override
          public void onLoadFailed(@NonNull Exception e) {
            if (isCurrentRequest(toStart)) {
              onLoadFailedInternal(toStart, e);
            }
          }
        });
  }
  ...
}

可以看到startNext()中又调用了startNextLoad()方法,我重点看第19行和第31行,先说第19行,作用是获取数据加载器,代码如下:

final class DecodeHelper<Transcode> {
...
List<LoadData<?>> getLoadData() {
    if (!isLoadDataSet) {
      isLoadDataSet = true;
      loadData.clear();
      List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
      //noinspection ForLoopReplaceableByForEach to improve perf
      for (int i = 0, size = modelLoaders.size(); i < size; i++) {
        ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
        LoadData<?> current = modelLoader.buildLoadData(model, width, height, options);
        if (current != null) {
          loadData.add(current);
        }
      }
    }
    return loadData;
  }
  ...
}

第7行这里从Glide实例的Registry注册表中获取modelLoaders。
注意:在注册表中注册的都是ModelLoader的实现ModelLoaderFactory静态工厂类,当调用Registry的getModelLoaders时会调用工厂类中的build()方法。
因为我们以String为例,所以这里的model是String类型。我们来看String类型有哪些modelLoaders:

public class Glide{
...
Glide(){
	registry
	.append(String.class, InputStream.class, new DataUrlLoader.StreamFactory<String>())
    .append(String.class, InputStream.class, new StringLoader.StreamFactory())
    .append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())
    .append(String.class, AssetFileDescriptor.class, new StringLoader.AssetFileDescriptorFactory())
}
...
}

这里我们以StringLoader.StreamFactory为例子,调用了getModelLoaders()方法,会执行StringLoader.StreamFactory的build()方法。代码如下:

public class StringLoader{
	public static class StreamFactory{
		@NonNull
    @Override
    public ModelLoader<String, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) {
      return new StringLoader<>(multiFactory.build(Uri.class, InputStream.class));
    }
	}
}

在build()方法中构建了StringLoader对象,里面调用了multiFactory.build()方法,这时我们需要在Glide的registry注册表中找到参数为Uri.class, InputStream.class的Factory对象。这时候的重点是看HttpUriLoader.Factory().build()。

registry
.append(Uri.class, InputStream.class, new HttpUriLoader.Factory())

就这样不断追踪下去最终返回的是HttpGlideUrlLoader对象:

public class HttpGlideUrlLoader{
...
public static class Factory{
@NonNull
    @Override
    public ModelLoader<GlideUrl, InputStream> build(MultiModelLoaderFactory multiFactory) {
      return new HttpGlideUrlLoader(modelCache);
    }
}
...
}

接下来我们看看StringLoader构造方法:

public class StringLoader{
...
public StringLoader(ModelLoader<Uri, Data> uriLoader) {
    this.uriLoader = uriLoader;
  }
  ...
}

就是把HttpGlideUrlLoader对象封装进去,现在我们回到刚才的DecodeHelper.getLoadData()方法,获取完modelLoaders,遍历了一遍并执行modelLoader.buildLoadData()方法构建loadData对象。我们以modelLoader为上面分析的StringLoader对象继续看buildLoadData()的实现:

public class StringLoader{
...
@Override
  public LoadData<Data> buildLoadData(
      @NonNull String model, int width, int height, @NonNull Options options) {
    Uri uri = parseUri(model);
    if (uri == null || !uriLoader.handles(uri)) {
      return null;
    }
    return uriLoader.buildLoadData(uri, width, height, options);
  }
...
}

这里调用了uriLoader.buildLoadData(),也就是HttpGlideUrlLoader类中的buildLoadData()方法:

public class HttpGlideUrlLoader{
...
@Override
  public LoadData<InputStream> buildLoadData(
      @NonNull GlideUrl model, int width, int height, @NonNull Options options) {
    // GlideUrls memoize parsed URLs so caching them saves a few object instantiations and time
    // spent parsing urls.
    GlideUrl url = model;
    if (modelCache != null) {
      url = modelCache.get(model, 0, 0);
      if (url == null) {
        modelCache.put(model, 0, 0, model);
        url = model;
      }
    }
    int timeout = options.get(TIMEOUT);
    return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
  }
  ...
}

可以看到,最后返回的是封装了HttpUrlFetcher的LoadData对象。现在我们回到SourceGenerator的startNextLoad()方法:

class SourceGenerator{
...
private void startNextLoad(final LoadData<?> toStart) {
    loadData.fetcher.loadData(
        helper.getPriority(),
        new DataCallback<Object>() {
          @Override
          public void onDataReady(@Nullable Object data) {
            if (isCurrentRequest(toStart)) {
              onDataReadyInternal(toStart, data);
            }
          }

          @Override
          public void onLoadFailed(@NonNull Exception e) {
            if (isCurrentRequest(toStart)) {
              onLoadFailedInternal(toStart, e);
            }
          }
        });
  }
  ...
}

我可以得知loadData的fetcher既是HttpUrlFetcher对象,所以这里调用的loadData()方法是在HttpUrlFetcher类中:

public class HttpUrlFetcher{
...
@Override
  public void loadData(
      @NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
    long startTime = LogTime.getLogTime();
    try {
      InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
      callback.onDataReady(result);
    } catch (IOException e) {
      if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "Failed to load data for url", e);
      }
      callback.onLoadFailed(e);
    } finally {
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));
      }
    }
  }

  private InputStream loadDataWithRedirects(
      URL url, int redirects, URL lastUrl, Map<String, String> headers) throws IOException {
    if (redirects >= MAXIMUM_REDIRECTS) {
      throw new HttpException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
    } else {
      try {
        if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
          throw new HttpException("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(timeout);
    urlConnection.setReadTimeout(timeout);
    urlConnection.setUseCaches(false);
    urlConnection.setDoInput(true);
    
    urlConnection.setInstanceFollowRedirects(false);

    urlConnection.connect();
    stream = urlConnection.getInputStream();
    if (isCancelled) {
      return null;
    }
    final int statusCode = urlConnection.getResponseCode();
    if (isHttpOk(statusCode)) {
      return getStreamForSuccessfulRequest(urlConnection);
    } else if (isHttpRedirect(statusCode)) {
      String redirectUrlString = urlConnection.getHeaderField("Location");
      if (TextUtils.isEmpty(redirectUrlString)) {
        throw new HttpException("Received empty or null redirect url");
      }
      URL redirectUrl = new URL(url, redirectUrlString);
      cleanup();
      return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
    } else if (statusCode == INVALID_STATUS_CODE) {
      throw new HttpException(statusCode);
    } else {
      throw new HttpException(urlConnection.getResponseMessage(), statusCode);
    }
  }
  ...
}

可以看到,这里的loadData()调用loadDataWithRedirects()方法获取数据流,loadDataWithRedirects方法使用了HttpURLConnection从网络获取数据。我们费了九牛二虎之力终于找到网络请求代码。
现在有了InputStream,还需要把它回调出去,在第9行调用了callback.onDataReady()方法,从上一步的startNextLoad()方法得知调用了SourceGenerator类的onDataReadyInternal()方法,代码如下:

class SourceGenerator{
...
void onDataReadyInternal(LoadData<?> loadData, Object data) {
        DiskCacheStrategy diskCacheStrategy = this.helper.getDiskCacheStrategy();
        if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
            this.dataToCache = data;
            this.cb.reschedule();
        } else {
            this.cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher, loadData.fetcher.getDataSource(), this.originalKey);
        }

    }
    ...
}

这里有个是否要缓存的策略,我们先不缓存直接看onDataFetcherReady()方法,这里的cb对象是在SourceGenerator对象创建时传入的,还记得SourceGenerator对象在什么时候创建的吗?是在DecodeJob运行时调用了getNextGenerator()方法创建的。DecodeJob本身实现了onDataFetcherReady()方法:

class DecodeJob<R>
    implements DataFetcherGenerator.FetcherReadyCallback{
    ...
@Override
  public void onDataFetcherReady(
      Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) {
    this.currentSourceKey = sourceKey;
    this.currentData = data;
    this.currentFetcher = fetcher;
    this.currentDataSource = dataSource;
    this.currentAttemptingKey = attemptedKey;
    if (Thread.currentThread() != currentThread) {
      runReason = RunReason.DECODE_DATA;
      callback.reschedule(this);
    } else {
      GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
      try {
        decodeFromRetrievedData();
      } finally {
        GlideTrace.endSection();
      }
    }
  }
  
  private void decodeFromRetrievedData() {
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
      logWithTimeAndKey(
          "Retrieved data",
          startFetchTime,
          "data: "
              + currentData
              + ", cache key: "
              + currentSourceKey
              + ", fetcher: "
              + currentFetcher);
    }
    Resource<R> resource = null;
    try {
      resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    } catch (GlideException e) {
      e.setLoggingDetails(currentAttemptingKey, currentDataSource);
      throwables.add(e);
    }
    if (resource != null) {
      notifyEncodeAndRelease(resource, currentDataSource);
    } else {
      runGenerators();
    }
  }
  ...
}

第18行onDataFetcherReady()中调用了decodeFromRetrievedData()方法解码数据,第39行decodeFromRetrievedData()通过调用decodeFromData()方法解码数据返回Resource对象,然后第45行调用notifyEncodeAndRelease()通知获取数据成功。代码如下:

class DecodeJob{
...
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
    if (resource instanceof Initializable) {
      ((Initializable) resource).initialize();
    }

    Resource<R> result = resource;
    LockedResource<R> lockedResource = null;
    if (deferredEncodeManager.hasResourceToEncode()) {
      lockedResource = LockedResource.obtain(resource);
      result = lockedResource;
    }

    notifyComplete(result, dataSource);

    stage = Stage.ENCODE;
    try {
      if (deferredEncodeManager.hasResourceToEncode()) {
        deferredEncodeManager.encode(diskCacheProvider, options);
      }
    } finally {
      if (lockedResource != null) {
        lockedResource.unlock();
      }
    }
    // Call onEncodeComplete outside the finally block so that it's not called if the encode process
    // throws.
    onEncodeComplete();
  }
  
  private void notifyComplete(Resource<R> resource, DataSource dataSource) {
    setNotifiedOrThrow();
    callback.onResourceReady(resource, dataSource);
  }
  ...
}

这里notifyEncodeAndRelease()调用了notifyComplete()方法通知完成,notifyComplete()调用callback.onResourceReady()进行回调数据,onResourceReady()在EngineJob类中实现了此方法:

class EngineJob{
...
@Override
  public void onResourceReady(Resource<R> resource, DataSource dataSource) {
    synchronized (this) {
      this.resource = resource;
      this.dataSource = dataSource;
    }
    notifyCallbacksOfResult();
  }
  
  @Synthetic
  void notifyCallbacksOfResult() {
    ResourceCallbacksAndExecutors copy;
    Key localKey;
    EngineResource<?> localResource;
    synchronized (this) {
      stateVerifier.throwIfRecycled();
      if (isCancelled) {
        resource.recycle();
        release();
        return;
      } else if (cbs.isEmpty()) {
        throw new IllegalStateException("Received a resource without any callbacks to notify");
      } else if (hasResource) {
        throw new IllegalStateException("Already have resource");
      }
      engineResource = engineResourceFactory.build(resource, isCacheable, key, resourceListener);
      hasResource = true;
      copy = cbs.copy();
      incrementPendingCallbacks(copy.size() + 1);

      localKey = key;
      localResource = engineResource;
    }

    engineJobListener.onEngineJobComplete(this, localKey, localResource);

    for (final ResourceCallbackAndExecutor entry : copy) {
      entry.executor.execute(new CallResourceReady(entry.cb));
    }
    decrementPendingCallbacks();
  }
  ...
}

onResourceReady()调用notifyCallbacksOfResult()通知回调结果,notifyCallbacksOfResult()中主要看第40行,执行了一个线程CallResourceReady(),这个线程做了什么呢,我们看它的run()方法:

class EngineJob{
...
@Override
private class CallResourceReady implements Runnable {

    public void run() {
      synchronized (cb.getLock()) {
        synchronized (EngineJob.this) {
          if (cbs.contains(cb)) {
            // Acquire for this particular callback.
            engineResource.acquire();
            callCallbackOnResourceReady(cb);
            removeCallback(cb);
          }
          decrementPendingCallbacks();
        }
      }
    }
}
@Synthetic
  @GuardedBy("this")
  void callCallbackOnResourceReady(ResourceCallback cb) {
    try {
      cb.onResourceReady(engineResource, dataSource);
    } catch (Throwable t) {
      throw new CallbackException(t);
    }
  }
  ...
}

run()中调用了callCallbackOnResourceReady(),然后调用cb.onResourceReady回调数据,cb就是SingleRequest对象,由于代码较多这里直接给出关键代码:

public final class SingleRequest{
...
private void onResourceReady(){
...
target.onResourceReady(result, animation);
...
}
...
}

这里的target就是调用into()方法时构建的DrawableImageViewTarget对象。所以这里就进入了DrawableImageViewTarget父类ImageViewTarget的onResourceReady()方法,再调用DrawableImageViewTarget的setResource()方法,过程方法比较简单就不列了,这里直接给出最终的方法:

public class DrawableImageViewTarget extends ImageViewTarget<Drawable> {
...
  @Override
  protected void setResource(@Nullable Drawable resource) {
    view.setImageDrawable(resource);
  }
}

到此就把获取到的图片数据通过setImageDrawable()方法设置给了imageView控件,把图片展示出来了。

总结

看到这里,是不是感觉晕晕的?Glide帮我们做了非常多的事情,回调数据当然也很深。
真难相信这么短短的一行代码:Glide.with(this).load(url).into(imageView); 竟然如此的复杂,我们还仅仅是对流程简单的分析,我们下一篇再来探索下Glide的缓存机制。

参考资料
郭神 Android图片加载框架最全解析(二),从源码的角度理解Glide的执行流程

发布了64 篇原创文章 · 获赞 68 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/sange77/article/details/104579777