Glide4.9源码阅读之一次请求的流程

写在前面:
源码位置:https://github.com/bumptech/glide
本文中对应的版本为v4.9
源码阅读:
常用方式为:

Glide.with(fragment)
   .load(myUrl)
   .placeholder(placeholder)
   .fitCenter()
   .into(imageView);

那么便以此为切入点进行阅读,首先查看Glide的with方法。

/**
 * Begin a load with Glide that will be tied to the given
 * {@link android.support.v4.app.Fragment}'s lifecycle and that uses the given
 * {@link android.support.v4.app.Fragment}'s default options.
 *
 * @param fragment The fragment to use.
 * @return A RequestManager for the given Fragment that can be used to start a load.
 */
@NonNull
public static RequestManager with(@NonNull Fragment fragment) {
  return getRetriever(fragment.getActivity()).get(fragment);
}

此方法返回一个RequestManager,用于加载图片。与之类似的方法还有几个,如:

@NonNull
public static RequestManager with(@NonNull Activity activity) {
  return getRetriever(activity).get(activity);
}
/**
 * Begin a load with Glide by passing in a context.
 *
 * 

Any requests started using a context will only have the application level options applied * and will not be started or stopped based on lifecycle events. In general, loads should be * started at the level the result will be used in. If the resource will be used in a view in a * child fragment, the load should be started with {@link #with(android.app.Fragment)}} using that * child fragment. Similarly, if the resource will be used in a view in the parent fragment, the * load should be started with {@link #with(android.app.Fragment)} using the parent fragment. In * the same vein, if the resource will be used in a view in an activity, the load should be * started with {@link #with(android.app.Activity)}}.

* *

This method is appropriate for resources that will be used outside of the normal fragment * or activity lifecycle (For example in services, or for notification thumbnails).

* * @param context Any context, will not be retained. * @return A RequestManager for the top level application that can be used to start a load. * @see #with(android.app.Activity) * @see #with(android.app.Fragment) * @see #with(android.support.v4.app.Fragment) * @see #with(android.support.v4.app.FragmentActivity) */ @NonNull public static RequestManager with(@NonNull Context context) { return getRetriever(context).get(context); }

其中,传入context的with方法注释有一大坨,大意是不同的参数类型对应不同的生命周期,尽量选择最合适的with方法来用。
那么RequestManager是什么呢,我们先进源码查看一下:

/**
 * A class for managing and starting requests for Glide. Can use activity, fragment and connectivity
 * lifecycle events to intelligently stop, start, and restart requests. Retrieve either by
 * instantiating a new object, or to take advantage built in Activity and Fragment lifecycle
 * handling, use the static Glide.load methods with your Fragment or Activity.
 *
 * @see Glide#with(android.app.Activity)
 * @see Glide#with(android.support.v4.app.FragmentActivity)
 * @see Glide#with(android.app.Fragment)
 * @see Glide#with(android.support.v4.app.Fragment)
 * @see Glide#with(Context)
 */
public class RequestManager implements LifecycleListener,
    ModelTypes> {
        ......

注释的大意是,这个类负责管理Glide的请求,可以使用activity或者fragment等生命周期实现请求的开始、停止、重新开始等动作,可以通过以下方式获取,1,直接new一个对象,2.在activity或fragment的生命周期内使用Glide.with来获取。
再来看看getRetriever方法:

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

那么RequestManagerRetriver类是什么呢?

/**
 * A collection of static methods for creating new {@link com.bumptech.glide.RequestManager}s or
 * retrieving existing ones from activities and fragment.
 */
public class RequestManagerRetriever implements Handler.Callback {
    ......

注释大意是,这个类包含了一系列的用于创建RequestManager对象或获取一个已经存在的RequestManager对象的静态方法。那么Glide.get(context)做了什么呢?

/**
 * Get the singleton.
 *
 * @return the singleton
 */
@NonNull
public static Glide get(@NonNull Context context) {
  if (glide == null) {
    synchronized (Glide.class) {
      if (glide == null) {
        checkAndInitializeGlide(context);
      }
    }
  }

  return glide;
}

get方法用来获取对象,创建对象时进行了初始化。

private static void checkAndInitializeGlide(@NonNull Context context) {
  // In the thread running initGlide(), one or more classes may call Glide.get(context).
  // Without this check, those calls could trigger infinite recursion.
  if (isInitializing) {
    throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
        + " use the provided Glide instance instead");
  }
  isInitializing = true;
  initializeGlide(context);
  isInitializing = false;
}

那么 initializeGlide(context);做了什么呢,可以猜到初始化的逻辑在这个方法中。下面是这个方法的代码,可以看到还是挺长的。

@SuppressWarnings("deprecation")
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
  Context applicationContext = context.getApplicationContext();
  GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
  List manifestModules = Collections.emptyList();
  if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
    manifestModules = new ManifestParser(applicationContext).parse();
  }

  if (annotationGeneratedModule != null
      && !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
    Set> excludedModuleClasses =
        annotationGeneratedModule.getExcludedModuleClasses();
    Iterator iterator = manifestModules.iterator();
    while (iterator.hasNext()) {
      com.bumptech.glide.module.GlideModule current = iterator.next();
      if (!excludedModuleClasses.contains(current.getClass())) {
        continue;
      }
      if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);
      }
      iterator.remove();
    }
  }

  if (Log.isLoggable(TAG, Log.DEBUG)) {
    for (com.bumptech.glide.module.GlideModule glideModule : manifestModules) {
      Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
    }
  }

  RequestManagerRetriever.RequestManagerFactory factory =
      annotationGeneratedModule != null
          ? annotationGeneratedModule.getRequestManagerFactory() : null;
  builder.setRequestManagerFactory(factory);
  for (com.bumptech.glide.module.GlideModule module : manifestModules) {
    module.applyOptions(applicationContext, builder);
  }
  if (annotationGeneratedModule != null) {
    annotationGeneratedModule.applyOptions(applicationContext, builder);
  }
  Glide glide = builder.build(applicationContext);
  for (com.bumptech.glide.module.GlideModule module : manifestModules) {
    module.registerComponents(applicationContext, glide, glide.registry);
  }
  if (annotationGeneratedModule != null) {
    annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
  }
  applicationContext.registerComponentCallbacks(glide);
  Glide.glide = glide;
}

首先,第4行 GeneratedAppGlideModule 不知道是什么,通过查阅资料后疑惑得到解答。Glide有自己的默认配置,但用户可以定制自己的配置,如何实现呢,
方式1:在Manifest中声明自定义类
方式2:使用注解
关于自定义配置,暂不讨论,先看initializeGlide的逻辑,主要做了以下几件事:
使用反射动态创建注解定义AppGildeModule的实现类或者反射动态创建Manifest定义的GlideModule的实现类
将AppGlideModule的实现类或者GlideModule的实现类中的Glide的配置信息设置到GlideBuilder中
使用GlideBuilder根据配置信息构建Glide对象
将AppGlideModule的实现类或者GlideModule的实现类的Glide组件注册到glide中
glide监听Application的组件生命周期
我们再看下 Glide glide = builder.build(applicationContext);内部具体做了什么:

@NonNull
Glide build(@NonNull Context context) {
  if (sourceExecutor == null) {
      // 设置执行网络请求的线程池
    sourceExecutor = GlideExecutor.newSourceExecutor(); 
  }

  if (diskCacheExecutor == null) {
      // 设置磁盘缓存线程池
    diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
  }

  if (animationExecutor == null) {
       // 设置动画线程池
    animationExecutor = GlideExecutor.newAnimationExecutor();
  }

  if (memorySizeCalculator == null) {
       // 这个类是用来计算内存缓存的一些数据的,如缓存大小
    memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
  }

  if (connectivityMonitorFactory == null) {
      // 用于创建监控网络的类(DefaultConnectivityMonitor或NullConnectivityMonitor)
      // DefaultConnectivityMonitor实现了LifecycleListener接口,与Activity、fragment、application等生命周期有同步
      // 通过监控网络的开关,提供在网络恢复时会重新执行请求的能力
    connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
  }

  if (bitmapPool == null) {
    int size = memorySizeCalculator.getBitmapPoolSize();
    if (size > 0) {
      bitmapPool = new LruBitmapPool(size);
    } else {
      bitmapPool = new BitmapPoolAdapter();
    }
  }

  if (arrayPool == null) {
    arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
  }

  if (memoryCache == null) {
    memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
  }

  if (diskCacheFactory == null) {
      // 磁盘缓存的工厂类,提供建立磁盘缓存的能力,关联类DiskLruCacheWrapper
    diskCacheFactory = new InternalCacheDiskCacheFactory(context);
  }

  if (engine == null) {
      // 创建engine,engine是非常重要的存在,主要管理请求,和缓存相关工作
    engine =
        new Engine(
            memoryCache,
            diskCacheFactory,
            diskCacheExecutor,
            sourceExecutor,
            GlideExecutor.newUnlimitedSourceExecutor(),
            GlideExecutor.newAnimationExecutor(),
            isActiveResourceRetentionAllowed);
  }
  // 如果调用GlideBuilder的addGlobalRequestListener方法,将添加一个listener到defaultRequestListeners,以后每个请求都会回调到listener中
  if (defaultRequestListeners == null) {
    defaultRequestListeners = Collections.emptyList();
  } else {
    defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);// 这个小细节挺有趣的,作用是返回一个不可以修改的list
  }

  RequestManagerRetriever requestManagerRetriever =
      new RequestManagerRetriever(requestManagerFactory);

  return new Glide(
      context,
      engine,
      memoryCache,
      bitmapPool,
      arrayPool,
      requestManagerRetriever,
      connectivityMonitorFactory,
      logLevel,
      defaultRequestOptions.lock(),
      defaultTransitionOptions,
      defaultRequestListeners,
      isLoggingRequestOriginsEnabled);
}

上面对创建了Glide实例,但是engine内部我们还没有分析,暂时搁置,继续回到Glide.with方法,我们查看了getRetriever(context).get(context);方法的前半部分,后半部分,即get方法做了什么呢。

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

get方法的入参即with方法的入参,也是有几种类型(Activity/context/fragment…)。不论哪个方法,当检测到是backGroundThread的时候,执行了get方法:

@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) {
      return get(((ContextWrapper) context).getBaseContext());
    }
  }

  return getApplicationManager(context);
}

如果是Application的context,则返回getApplicationManager(context);如果不是Application的context,最终通过递归的操作也会返回getApplicationManager(context);

@NonNull
private RequestManager getApplicationManager(@NonNull 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.

        // TODO(b/27524013): Factor out this Glide.get() call.
        Glide glide = Glide.get(context.getApplicationContext());
        applicationManager =
            factory.build(
                glide,
                new ApplicationLifecycle(),
                new EmptyRequestManagerTreeNode(),
                context.getApplicationContext());
      }
    }
  }

  return applicationManager;
}

可以此时返回的requestManager是个单例。如果不是子线程呢,会执行get方法后面的xxxGet方法,如:

@SuppressWarnings({"deprecation", "DeprecatedIsStillUsed"})
@Deprecated
@NonNull
private RequestManager fragmentGet(@NonNull Context context,
    @NonNull android.app.FragmentManager fm,
    @Nullable android.app.Fragment parentHint,
    boolean isParentVisible) {
  RequestManagerFragment current = getRequestManagerFragment(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;
}

这个方法里面创建了RequestManager,先看getRequestManagerFragment:

@SuppressWarnings("deprecation")
@NonNull
private RequestManagerFragment getRequestManagerFragment(
    @NonNull final android.app.FragmentManager fm,
    @Nullable android.app.Fragment parentHint,
    boolean isParentVisible) {
  RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
  if (current == null) {
    current = pendingRequestManagerFragments.get(fm);
    if (current == null) {
      current = new RequestManagerFragment();
      current.setParentFragmentHint(parentHint);
      if (isParentVisible) {
        current.getGlideLifecycle().onStart();
      }
      pendingRequestManagerFragments.put(fm, current);
      fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
      handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
    }
  }
  return current;
}

这个方法创建(复用)了一个fragment,这是一个特殊的fragment:

/**
 * A view-less {@link android.app.Fragment} used to safely store an {@link
 * com.bumptech.glide.RequestManager} that can be used to start, stop and manage Glide requests
 * started for targets the fragment or activity this fragment is a child of.
 *
 * @see com.bumptech.glide.manager.SupportRequestManagerFragment
 * @see com.bumptech.glide.manager.RequestManagerRetriever
 * @see com.bumptech.glide.RequestManager
 */

其是一个空的fragment,主要用于监听生命周期,其内部有RequestManager变量和lifeCycle变量。回到fragmentGet方法,获取到feagment后,获取fragment的RequestManager,如果为空则新建一个RequestManager。
到此为止,已经获取到了RequestManager,Glide.with方法告一段落。

Glide.with(fragment)
   .load(myUrl)
   .placeholder(placeholder)
   .fitCenter()
   .into(imageView);

下面看下load方法:

/**
 * Equivalent to calling {@link #asDrawable()} and then {@link RequestBuilder#load(String)}.
 *
 * @return A new request builder for loading a {@link Drawable} using the given model.
 */
@NonNull
@CheckResult
@Override
public RequestBuilder load(@Nullable String string) {
  return asDrawable().load(string);
}

load方法有很多重载版本,但第一部分,都是执行了asDrawable方法。其根据不同的类型(一般是Drawable)返回一个RequestBuilder,其负责构建Request相关动作。再看第二部分的load方法,在RequestBuilder内部:

public RequestBuilder load(@Nullable String string) {
  return loadGeneric(string);
}


@NonNull
private RequestBuilder loadGeneric(@Nullable Object model) {
  this.model = model;
  isModelSet = true;
  return this;
}

到此为止没有发起请求,只是初始化一些变量。再看into方法:

/**
 * Sets the {@link ImageView} the resource will be loaded into, cancels any existing loads into
 * the view, and frees any resources Glide may have previously loaded into the view so they may be
 * reused.
 *
 * @see RequestManager#clear(Target)
 *
 * @param view The view to cancel previous loads for and load the new resource into.
 * @return The
 * {@link com.bumptech.glide.request.target.Target} used to wrap the given {@link ImageView}.
 */
@NonNull
public ViewTarget into(@NonNull ImageView view) {
  Util.assertMainThread();
  Preconditions.checkNotNull(view);

  BaseRequestOptions requestOptions = this;
  if (!requestOptions.isTransformationSet()
      && requestOptions.isTransformationAllowed()
      && view.getScaleType() != null) {
    // Clone in this method so that if we use this RequestBuilder to load into a View and then
    // into a different target, we don't retain the transformation applied based on the previous
    // View's scale type.
    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());
}

前半部分重新构建requestOptions,不需要点进去看,大概知道是跟填充模式有关的构建,直接看后半部分的逻辑,即into方法,传入的参数有几个,分别是target、requestOptions、线程池。

@NonNull
@Synthetic
> Y into(
    @NonNull Y target,
    @Nullable RequestListener targetListener,
    Executor callbackExecutor) {
  return into(target, targetListener, /*options=*/ this, callbackExecutor);
}

private > Y into(
    @NonNull Y target,
    @Nullable RequestListener targetListener,
    BaseRequestOptions options,
    Executor callbackExecutor) {
  Preconditions.checkNotNull(target);
  if (!isModelSet) {
    throw new IllegalArgumentException("You must call #load() before calling #into()");
  }
  // 构建Request
  Request request = buildRequest(target, targetListener, options, callbackExecutor);
  // 判断重复请求
  Request previous = target.getRequest();
  if (request.isEquivalentTo(previous)
      && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
    request.recycle();
    // If the request is completed, beginning again will ensure the result is re-delivered,
    // triggering RequestListeners and Targets. If the request is failed, beginning again will
    // restart the request, giving it another chance to complete. If the request is already
    // running, we can let it continue running without interruption.
    if (!Preconditions.checkNotNull(previous).isRunning()) {
      // Use the previous request rather than the new one to allow for optimizations like skipping
      // setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
      // that are done in the individual Request.
      previous.begin();
    }
    return target;
  }

  requestManager.clear(target);
  target.setRequest(request);
  // 进入请求的流程
  requestManager.track(target, request);

  return target;
}

查看下 requestManager.track(target, request):

synchronized void track(@NonNull Target target, @NonNull Request request) {
  targetTracker.track(target); // 存储active状态的target
  requestTracker.runRequest(request); // 发起请求
}

/**
 * Starts tracking the given request.
 */
public void runRequest(@NonNull Request request) {
  requests.add(request); // 存储request
  if (!isPaused) {
    request.begin();
  } else {
    request.clear();
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
      Log.v(TAG, "Paused, delaying request");
    }
    pendingRequests.add(request); // 存储request
  }
}

两处存储request的地方,有什么区别呢?分别看下注释:

// Most requests will be for views and will therefore be held strongly (and safely) by the view
// via the tag. However, a user can always pass in a different type of target which may end up not
// being strongly referenced even though the user still would like the request to finish. Weak
// references are therefore only really functional in this context for view targets. Despite the
// side affects, WeakReferences are still essentially required. A user can always make repeated
// requests into targets other than views, or use an activity manager in a fragment pager where
// holding strong references would steadily leak bitmaps and/or views.
private final Set requests =
    Collections.newSetFromMap(new WeakHashMap());
// A set of requests that have not completed and are queued to be run again. We use this list to
// maintain hard references to these requests to ensure that they are not garbage collected
// before they start running or while they are paused. See #346.
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
private final List pendingRequests = new ArrayList<>();

requests:不是很理解注释的意思.
pendingRequests:一个未结束的request放入队列中,以便将来开始请求,强引用的作用是在这个request暂停时或者未开始时避免其被gc掉。
接下来看下request是如何开始的,前面request.begain()这行作为切入点:

有几个实现类,那么此处具体是哪个实现类呢?我们回到RequestBuilder.into方法查看:
Request request = buildRequest(target, targetListener, options, callbackExecutor);

再进入buildRequest方法:

private Request buildRequest(......) {
  return buildRequestRecursive(
     ......);
}

private Request buildRequestRecursive(
    ......) {

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

  Request mainRequest =
      buildThumbnailRequestRecursive(
          ......);

  ......

  Request errorRequest =
      errorBuilder.buildRequestRecursive(
          ......);
  errorRequestCoordinator.setRequests(mainRequest, errorRequest);
  return errorRequestCoordinator;
}

private Request buildThumbnailRequestRecursive(
   ......) {
  if (thumbnailBuilder != null) {
   ......
    ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
    Request fullRequest =
        obtainRequest(
            ......);
    isThumbnailBuilt = true;
    // Recursively generate thumbnail requests.
    Request thumbRequest =
        thumbnailBuilder.buildRequestRecursive(
            ......);
    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(
            ......);
    BaseRequestOptions thumbnailOptions =
        requestOptions.clone().sizeMultiplier(thumbSizeMultiplier);

    Request thumbnailRequest =
        obtainRequest(
           ......);

    coordinator.setRequests(fullRequest, thumbnailRequest);
    return coordinator;
  } else {
    // Base case: no thumbnail.
    return obtainRequest(
       ......);
  }
}

可以发现所有的request都是通过obtainRequest来创建的:

private Request obtainRequest(
    Target target,
    RequestListener targetListener,
    BaseRequestOptions requestOptions,
    RequestCoordinator requestCoordinator,
    TransitionOptions transitionOptions,
    Priority priority,
    int overrideWidth,
    int overrideHeight,
    Executor callbackExecutor) {
  return SingleRequest.obtain(
      context,
      glideContext,
      model,
      transcodeClass,
      requestOptions,
      overrideWidth,
      overrideHeight,
      priority,
      target,
      targetListener,
      requestListeners,
      requestCoordinator,
      glideContext.getEngine(),
      transitionOptions.getTransitionFactory(),
      callbackExecutor);
}

所以,至此疑惑得到解决,request是通过SingleRequest类获取的,而SingleRequest类的obtain方法,尝试从对象池中取出对象,如果对象为空,则创建一个新的对象。找到具体实现类后,就可以继续查看其begin方法了。

@Override
public synchronized void begin() {
  assertNotCallingCallbacks();
  stateVerifier.throwIfRecycled();
  startTime = LogTime.getLogTime(); // 记录开始时间
  if (model == null) { // mode是load方法传进来的参数,如url string
    if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
      width = overrideWidth;
      height = overrideHeight;
    }
    // Only log at more verbose log levels if the user has set a fallback drawable, because
    // fallback Drawables indicate the user expects null models occasionally.
    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 we're restarted after we're complete (usually via something like a notifyDataSetChanged
  // that starts an identical request into the same Target or View), we can simply use the
  // resource and size we retrieved the last time around and skip obtaining a new size, starting a
  // new load etc. This does mean that users who want to restart a load because they expect that
  // the view size has changed will need to explicitly clear the View or Target before starting
  // the new load.
  if (status == Status.COMPLETE) {
    onResourceReady(resource, DataSource.MEMORY_CACHE);
    return;
  }

  // Restarts for requests that are neither complete nor running can be treated as new requests
  // and can run again from the beginning.

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

1.先判断是不是传进来的参数如url是空的,如果是非法的,进入失败状态;
2.再判断是不是正在请求中,如果是,抛出异常;
3.再判断是不是请求完成了,如果是则调用onResourceReady,最终回调到UI部分;
4.再判断是不是size已经合法了,如果是就执行onSizeReady(关于overrideWidth&overrideHeight的设置请参见下面的示例代码)
5.再判断是是不是可以回调onLoadStarted设置placeHolder
示例代码:

RequestOptions options = new RequestOptions()
.placeholder(R.mipmap.ic_launcher)//加载成功之前占位图
        .error(R.mipmap.ic_launcher)//加载错误之后的错误图
        .override(400,400)//指定图片的尺寸
        .fitCenter() //指定图片的缩放类型为fitCenter (等比例缩放图片,宽或者是高等于ImageView的宽或者是高。)
        .centerCrop()//指定图片的缩放类型为centerCrop (等比例缩放图片,直到图片的狂高都大于等于ImageView的宽度,然后截取中间的显示。)
        .circleCrop()//指定图片的缩放类型为centerCrop (圆形)
        .skipMemoryCache(true)//跳过内存缓存
        .diskCacheStrategy(DiskCacheStrategy.ALL)//缓存所有版本的图像
        .diskCacheStrategy(DiskCacheStrategy.NONE)//跳过磁盘缓存
        .diskCacheStrategy(DiskCacheStrategy.DATA)//只缓存原来分辨率的图片
        .diskCacheStrategy(DiskCacheStrategy.RESOURCE)//只缓存最终的图片 ;
Glide.with(this).load(url).apply(options).into(img);

看到这里,依然不知道request是怎么执行请求动作的,再回头看看begin方法,发现onSizeReady方法有玄机:

/**
 * A callback method that should never be invoked directly.
 */
@Override
public synchronized void onSizeReady(int width, int height) {
  stateVerifier.throwIfRecycled();
  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);

  // This is a hack that's only useful for testing right now where loads complete synchronously
  // even though under any executor running on any thread but the main thread, the load would
  // have completed asynchronously.
  if (status != Status.RUNNING) {
    loadStatus = null;
  }
  if (IS_VERBOSE_LOGGABLE) {
    logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
  }
}

可以看见,最后的engine.load方法是关键。首先,传了很多的参数到load方法中,这些参数我们之前都没有距离了解过来源和意义。先来了解下:
我们继续看engine.load方法执行了什么,这个方法很长,一步一步分析:

/**
 * Starts a load for the given arguments.
 *
 * 

Must be called on the main thread. * *

The flow for any request is as follows: * *

    *
  • Check the current set of actively used resources, return the active resource if present, * and move any newly inactive resources into the memory cache. *
  • Check the memory cache and provide the cached resource if present. *
  • Check the current set of in progress loads and add the cb to the in progress load if one * is present. *
  • Start a new load. *
* *

Active resources are those that have been provided to at least one request and have not yet * been released. Once all consumers of a resource have released that resource, the resource then * goes to cache. If the resource is ever returned to a new consumer from cache, it is re-added to * the active resources. If the resource is evicted from the cache, its resources are recycled and * re-used if possible and the resource is discarded. There is no strict requirement that * consumers release their resources so active resources are held weakly. * * @param width The target width in pixels of the desired resource. * @param height The target height in pixels of the desired resource. * @param cb The callback that will be called when the load completes. */ public synchronized LoadStatus load( GlideContext glideContext, Object model, Key signature, int width, int height, Class resourceClass, Class transcodeClass, Priority priority, DiskCacheStrategy diskCacheStrategy, Map, 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; // 创建key,用来做什么?(EngineKey:An in memory only cache key used to multiplex loads.) // 从类的注释上来看,是用来做缓存的key的 EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations, resourceClass, transcodeClass, options); // 此处是从尝试根据上面生成的key从ActiveResources中取出资源,ActiveResources类维护了一个map,key是EngineKey,value是ReourceWeakReference // 从名字来看,是当前激活状态下的资源缓存,即有一个request请求到了资源,但是还没释放,就存在这个ActiveResource中,算是一种轻量级临时内存缓存。 EngineResource active = loadFromActiveResources(key, isMemoryCacheable); if (active != null) { cb.onResourceReady(active, DataSource.MEMORY_CACHE); if (VERBOSE_IS_LOGGABLE) { logWithTimeAndKey("Loaded resource from active resources", startTime, key); } return null; } // 如果ActiveResources中没有本次请求所对应的资源,就尝试从MemoryCache中获取 // 如果内存缓存中存在资源,则返回,并put到ActiveResources的map中 EngineResource cached = loadFromCache(key, isMemoryCacheable); if (cached != null) { cb.onResourceReady(cached, DataSource.MEMORY_CACHE); if (VERBOSE_IS_LOGGABLE) { logWithTimeAndKey("Loaded resource from cache", startTime, key); } return null; } // 如果内存缓存中不存在资源,则从jobs中根据key获取一个EngineJob // 如果job不是空,则执行EngineJob的addCallback方法传入callbackExecutor,这个callbackExecutor是从何处传来的呢,可以回溯到RequestBuilde的into方法 // 如果不指定的话,默认传的是Executors.mainThreadExecutor(),其实就是一个主线程的handler机制,将任务post到主线程中执行 // private static final Executor MAIN_THREAD_EXECUTOR = // new Executor() { // private final Handler handler = new Handler(Looper.getMainLooper()); // // @Override // public void execute(@NonNull Runnable command) { // handler.post(command); // } // }; // 那么这个EngineJob取出来干什么呢,为什么要从这里取出来呢,我们先看看从哪里put到jobs中的 // 是在本方法后面的jobs.put(key, engineJob);这一行,且只有此处调用了put。 // 所以这是一种避免同一个request重复构建EngineJob的措施。 // 那么EngineJob到底是什么东西,还是不知道 EngineJob current = jobs.get(key, onlyRetrieveFromCache); if (current != null) { // 另外,cb这个参数类型是ResourceCallback,此处的cb实现类是SingleRequest,cb用来在请求complete的时候回调 // addCalback中会把这个job加到ResourceCallbacksAndExecutors中,最后也请求完成后会在EngineJob的notifyCallbacksOfResult方法中遍历cbs回调到之前添加cb(callback)中 current.addCallback(cb, callbackExecutor); if (VERBOSE_IS_LOGGABLE) { logWithTimeAndKey("Added to existing load", startTime, key); } return new LoadStatus(cb, current); } // 此处构建EngineJob,通过EngineJob类的注释(* A class that manages a load by adding and removing callbacks for for the load and notifying callbacks when the load completes.) // 大概知道这个类是管理一个请求的,包括添加和删除callback、请求结束后调用callback EngineJob engineJob = engineJobFactory.build( key, isMemoryCacheable, useUnlimitedSourceExecutorPool, useAnimationPool, onlyRetrieveFromCache); // 此处构建DecodeJob,这个类从注释可以知道,是用来对资源进行编码的 DecodeJob 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); }

看下engine.start方法:

public synchronized void start(DecodeJob decodeJob) {
  this.decodeJob = decodeJob;
  // 如果是从缓存decode就使用缓存线程池进行工作,否则就使用其他线程池执行任务,这里的其他线程池,
  // 可能是我们最初初始化Glide的时候创建的默认的线程池,也可能是用户设置的线程池
  GlideExecutor executor = decodeJob.willDecodeFromCache()
      ? diskCacheExecutor
      : getActiveSourceExecutor();
  executor.execute(decodeJob);
}

最终调用了GlideExecutor的execute方法:

@Override
public void execute(@NonNull Runnable command) {
  delegate.execute(command);
}

那么delegate的实现类是什么呢,就是start方法中获取的线程池类。假设是sourceExecutor那么便是初始化Glide 的时通过GlideExecutor.newSourceExecutor创建的。
我们execute方法执行的command是Runnable类型,就是我们传进来的decodeJob。他的run方法如下:

// We need to rethrow only CallbackException, but not other types of Throwables.
@SuppressWarnings("PMD.AvoidRethrowingException")
@Override
public void run() {
  // This should be much more fine grained, but since Java's thread pool implementation silently
  // swallows all otherwise fatal exceptions, this will at least make it obvious to developers
  // that something is failing.
  GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)", model);
  // Methods in the try statement can invalidate currentFetcher, so set a local variable here to
  // ensure that the fetcher is cleaned up either way.
  DataFetcher localFetcher = currentFetcher;
  try {
    if (isCancelled) {
      notifyFailed();
      return;
    }
    runWrapped();
  } catch (CallbackException e) {
    // If a callback not controlled by Glide throws an exception, we should avoid the Glide
    // specific debug logic below.
    throw e;
  } catch (Throwable t) {
    // Catch Throwable and not Exception to handle OOMs. Throwables are swallowed by our
    // usage of .submit() in GlideExecutor so we're not silently hiding crashes by doing this. We
    // are however ensuring that our callbacks are always notified when a load fails. Without this
    // notification, uncaught throwables never notify the corresponding callbacks, which can cause
    // loads to silently hang forever, a case that's especially bad for users using Futures on
    // background threads.
    if (Log.isLoggable(TAG, Log.DEBUG)) {
      Log.d(TAG, "DecodeJob threw unexpectedly"
          + ", isCancelled: " + isCancelled
          + ", stage: " + stage, t);
    }
    // When we're encoding we've already notified our callback and it isn't safe to do so again.
    if (stage != Stage.ENCODE) {
      throwables.add(t);
      notifyFailed();
    }
    if (!isCancelled) {
      throw t;
    }
    throw t;
  } finally {
    // Keeping track of the fetcher here and calling cleanup is excessively paranoid, we call
    // close in all cases anyway.
    if (localFetcher != null) {
      localFetcher.cleanup();
    }
    GlideTrace.endSection();
  }
}

可以看到一个DataFetcher类型的变量localFetcher,他被赋值为currentFetcher,至于currentFetcher何时被赋值呢,有好几处,本人没有debug,暂不知道是哪里赋值的,尝试向下看。
仅有一个有用的方法了,便是runWrapper了:

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

看起来是各种状态转换的逻辑。这个runReason的值是什么呢,init后他是INITIALIZE,所以走第一个分支,state初始值是null,通过getNextStage方法赋值:

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

走第一个分支,得到赋值。假设此处赋值为Stage.RESOURCE_CACHE,那么runWrapped()中的currentGenerator赋值为什么呢?

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

返回了ResourceCacheGenerator类型。runWrapped()中继续执行 runGenerators();方法:

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

  // Otherwise a generator started a new load and we expect to be called back in
  // onDataFetcherReady.
}

可以看到在while循环中不停的执行状态的转移。并不断执行currentGenerator.startNext():
currentGenerator有几个实现类,我们先看下SourceGenertor类的startNext:

@Override
public boolean startNext() {
    // 数据不为空的时候将数据缓存,第一次的时候这里是null
  if (dataToCache != null) {
    Object data = dataToCache;
    dataToCache = null;
    cacheData(data); // 缓存到磁盘
  }
   // 第一次的时候这里是null,赋值是在上面的CacheData方法中赋值的
  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;
      loadData.fetcher.loadData(helper.getPriority(), this);
    }
  }
  return started;
}

后半部分就是网络请求的执行了,fetcher有很多实现类,我们看HttpUrlFetcher:

@Override
public void loadData(@NonNull Priority priority,
    @NonNull DataCallback 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));
    }
  }
}

请求数据后回调到sourceGenerator中,假设请求成功,先从HttpUrlFetcher回调到sourceGenerator的onDataReady:

@Override
public void onDataReady(Object data) {
  DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
  if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
    dataToCache = data;
    // We might be being called back on someone else's thread. Before doing anything, we should
    // reschedule to get back onto Glide's thread.
    cb.reschedule();
  } else {
    cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,
        loadData.fetcher.getDataSource(), originalKey);
  }
}

然后又从sourceGenerator中继续回调到DecodeJob中(sourceGenerator是在这里创建的,创建set了callback),此处回调DecodeJob.onDataFetcherReady:

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

在调用下面方法:

private void notifyComplete(Resource resource, DataSource dataSource) {
  setNotifiedOrThrow();
  callback.onResourceReady(resource, dataSource);
}

这个callback是Engine中load方法中构造decodeJob的时候传过来的,实现类是EngineJob,EngineJob的onResourceReady方法中最终调用了:

@Synthetic
void notifyCallbacksOfResult() {
  ResourceCallbacksAndExecutors copy;
  Key localKey;
  EngineResource localResource;
  synchronized (this) {
    stateVerifier.throwIfRecycled();
    if (isCancelled) {
      // TODO: Seems like we might as well put this in the memory cache instead of just recycling
      // it since we've gotten this far...
      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);
    // Hold on to resource for duration of our callbacks below so we don't recycle it in the
    // middle of notifying if it synchronously released by one of the callbacks. Acquire it under
    // a lock here so that any newly added callback that executes before the next locked section
    // below can't recycle the resource before we call the callbacks.
    hasResource = true;
    copy = cbs.copy();
    incrementPendingCallbacks(copy.size() + 1);

    localKey = key;
    localResource = engineResource;
  }
  // listener是哪里传进来的?EngineJob的创建时使用Factory模式创建的,其factory的实现类是EngineJobFactory
  // EngineJobFactory对象里面维护了一个listener变量,类型是EngineJobListener,那么EngineJobFactory对象实例化是在哪里进行的呢?
  // 这个EngineJobFactory是在Engine的load方法中初始化的,传入的listener是this,显然,实现类是Engine
  listener.onEngineJobComplete(this, localKey, localResource);
  // 回调各个之前注册的callback
  for (final ResourceCallbackAndExecutor entry : copy) {
    entry.executor.execute(new CallResourceReady(entry.cb));
  }
  decrementPendingCallbacks();
}

上面的代码块中我发现listener的实现类是Engine,具体重写的方法是:

@SuppressWarnings("unchecked")
@Override
public synchronized void onEngineJobComplete(
    EngineJob engineJob, Key key, EngineResource resource) {
  // A null resource indicates that the load failed, usually due to an exception.
  if (resource != null) {
    resource.setResourceListener(key, this);
    // 将当前正在使用的资源放入轻量级缓存中,我们前面有见过这个东西
    if (resource.isCacheable()) {
      activeResources.activate(key, resource);
    }
  }
  // 前面在构建Engine的时候有提到过jobs,是为了避免重复构建job
  jobs.removeIfCurrent(key, engineJob);
}

@Override
public synchronized void onEngineJobCancelled(EngineJob engineJob, Key key) {
  jobs.removeIfCurrent(key, engineJob);
}

继续看notifyCallbacksOfResult()方法的后半部分,遍历了copy,即cbs,cbs前面在Engine.load方法中有提到过,每个任务对应一个cb(ResourceCallback),jobs中存储的是cb和阈值对应的Executor,所以,此处最终通过遍历的方式回调了所有的cb。不要忘记cb的实现是SingleRequest类。分析下SingleRequest类中的onResourceReady方法:

/**
 * Internal {@link #onResourceReady(Resource, DataSource)} where arguments are known to be safe.
 *
 * @param resource original {@link Resource}, never null
 * @param result object returned by {@link Resource#get()}, checked for type and never null
 *     
 */
private synchronized void onResourceReady(Resource resource, R result, DataSource dataSource) {
  // We must call isFirstReadyResource before setting status.
  boolean isFirstResource = isFirstReadyResource();
  status = Status.COMPLETE;
  this.resource = resource;

  if (glideContext.getLogLevel() <= Log.DEBUG) {
    Log.d(GLIDE_TAG, "Finished loading " + result.getClass().getSimpleName() + " from "
        + dataSource + " for " + model + " with size [" + width + "x" + height + "] in "
        + LogTime.getElapsedMillis(startTime) + " ms");
  }

  isCallingCallbacks = true;
  try {
    boolean anyListenerHandledUpdatingTarget = false;
    if (requestListeners != null) {
        // 这个requestListeners可以通过RequestBuilder传入,如:
        // GlideApp.with(context)
        //     .load(ResourceIds.raw.canonical)
        //     .listener(requestListener)
        //     .thumbnail(GlideApp.with(context)
        //     .load(thumbModel)
        //     .listener(requestListener)
        //     .override(100, 100)),
        //      imageView);
      for (RequestListener listener : requestListeners) {
        anyListenerHandledUpdatingTarget |=
            listener.onResourceReady(result, model, target, dataSource, isFirstResource);
      }
    }
    // targetListener 是通过Engine.load传进来的
    anyListenerHandledUpdatingTarget |=
        targetListener != null
            && targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);
    // 如果前面的targetListener返回false,才执行这里(这个思路类似view的点击事件体系)   
    if (!anyListenerHandledUpdatingTarget) {
        // 这里的代码跟动画有关,我们看下target对象的实现类ImageViewTarget
      Transition animation =
          animationFactory.build(dataSource, isFirstResource);
      target.onResourceReady(result, animation);
    }
  } finally {
    isCallingCallbacks = false;
  }

  notifyLoadSuccess();
}

target对象的实现类ImageViewTarget.onResourceReady:

@Override
public void onResourceReady(@NonNull Z resource, @Nullable Transition transition) {
  if (transition == null || !transition.transition(resource, this)) {
    setResourceInternal(resource);// 调用了view的设置资源的方法
  } else {
    maybeUpdateAnimatable(resource);// 调用了view的执行动画的方法
  }
}

那么Transition是什么呢?他是一个接口,注释:

/**
 * An interface that allows a transition to be applied to {@link android.view.View}s in {@link
 * com.bumptech.glide.request.target.Target}s in across resource types. Targets that wrap views will
 * be able to provide all of the necessary arguments and start the transition. Those that do not
 * will be unable to provide the necessary arguments and will therefore be forced to ignore the
 * transition. This interface is a compromise that allows view specific transition in Glide's
 * complex world of arbitrary resource types and arbitrary target types.
 *
 * @param  The type of the resource whose entrance will be transitioned.
 */
public interface Transition 

大意是这个类允许一个transition(过度转换动画)应用到view上,但是得提供所需要的参数,否则会忽略这个transition。
实现类有:

具体怎么用,示例:

DrawableCrossFadeFactory drawableCrossFadeFactory = new DrawableCrossFadeFactory.Builder(300).setCrossFadeEnabled(true).build();
Glide.with(this)
    .load(URL_JPG)
    .apply(new RequestOptions().placeholder(R.drawable.ic_launcher))
    .transition(DrawableTransitionOptions.with(drawableCrossFadeFactory))
    .into(imageView);

至此基本上一个流程就走完了,但是一些细节依然没有深入其中。后面会继续阅读。

你可能感兴趣的:(源码)