Android 图片加载框架Glide主流程源码分析

下一篇 Android 图片加载框架Glide缓存原理源码分析


Glide图片加载框架最近比较火,谷歌官方强烈推荐,使用也比较简单,功能强大,支持网络图片本地图片的加载,支持静态图片和动态图片。反正一句话就是很火很牛,我们需要它。

github地址:

https://github.com/bumptech/glide   点击打开链接

这里采用的Glide4.4版本进行分析,现在直接根据加载方法开始分析吧。


Glide.with(vh.imageView)
          .load(image.link)

          .into(vh.imageView);


先看Glide.with(),

public class Glide implements ComponentCallbacks2 {
  ...
  public static RequestManager with(View view) {
    return getRetriever(view.getContext()).get(view);
  }

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

可以看到17行开始构造Glide实例,进入到get()里面,

public class Glide implements ComponentCallbacks2 {
   ...
    /**
   * Get the singleton.
   *
   * @return the singleton
   */
  public static Glide get(Context context) {
    // 获取Glide单例
    if (glide == null) {
      synchronized (Glide.class) {
        if (glide == null) {
          checkAndInitializeGlide(context);
        }
      }
    }

    return glide;
  }
    
   ...
}
这里已经能看到构造了一个Glide单例,继续往里面看,看是怎么构造这个单例的


public class Glide implements ComponentCallbacks2 {
  ...
    /**
   * 检查并初始化Glide
   * @param context
   */
  private static void checkAndInitializeGlide(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;
  }

    private static void initializeGlide(Context context) {
    initializeGlide(context, new GlideBuilder());
  }

  @SuppressWarnings("deprecation")
  private static void initializeGlide(Context context, GlideBuilder builder) {
    // 初始化Glide
    Context applicationContext = context.getApplicationContext();
    // 获取GeneratedAppGlideModule的实例
    GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
    List manifestModules = Collections.emptyList();
    if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
      // 解析AndroidManifest.xml,把配置的自定义的GlideModule的实例保存到list中
      // 
      // 
      manifestModules = new ManifestParser(applicationContext).parse();
    }

    if (annotationGeneratedModule != null
        && !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
      // 这里有个疑问,annotationGeneratedModule.getExcludedModuleClasses()永远都是空的,根本不会执行下面的代码
      // 不知道这里加上这句判断有何作用
      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) {
      // 不在AndroidManifest.xml里面配置GlideModule,这个for进不来的,默认是不用配置的
      module.applyOptions(applicationContext, builder);
    }
    if (annotationGeneratedModule != null) {
      // 最新的glide4.0以上版本已经不再需要在AndroidManifest.xml中配置GlideModule;
      // applyOptions 是给自定义配置的,比如内存占比等,默认已经配置过
      annotationGeneratedModule.applyOptions(applicationContext, builder);
    }
    // 开始初始化Glide单例
    Glide glide = builder.build(applicationContext);
    // registerComponents 留给自定义的回调函数
    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;
  }
    
  ...
}
这个构造流程相当长,具体的注释已经写在代码中了,这里分析几个关键部分,

28-74行,获取到GeneratedAppGlideModule 的实例,如果这个实例为空,就去AndroidManifest.xml中去查找com.bumptech.glide.module.GlideModule,用过Glide都知道,如果要修改缓存等配置就需要继承GlideModule并扩展,其实4.0版本以后Glide就增加了用注解的方式生成GlideModule,再也不用AndroidManifest.xml中注册自定义的GlideModule,这样确实方便很多

28行,这里就是去生成GeneratedAppGlideModule实例,跟踪进入,

public class Glide implements ComponentCallbacks2 {
  ...
     @Nullable
  @SuppressWarnings({"unchecked", "deprecation", "TryWithIdenticalCatches"})
  private static GeneratedAppGlideModule getAnnotationGeneratedGlideModules() {
    // 通过GeneratedAppGlideModuleImpl名称去获取Class对象
    GeneratedAppGlideModule result = null;
    try {
      Class clazz =
          (Class)
              Class.forName("com.bumptech.glide.GeneratedAppGlideModuleImpl");
      result = clazz.newInstance();
    } catch (ClassNotFoundException e) {
      if (Log.isLoggable(TAG, Log.WARN)) {
        Log.w(TAG, "Failed to find GeneratedAppGlideModule. You should include an"
            + " annotationProcessor compile dependency on com.github.bumptech.glide:compiler"
            + " in your application and a @GlideModule annotated AppGlideModule implementation or"
            + " LibraryGlideModules will be silently ignored");
      }
    } catch (InstantiationException e) {
      throw new IllegalStateException("GeneratedAppGlideModuleImpl is implemented incorrectly."
          + " If you've manually implemented this class, remove your implementation. The Annotation"
          + " processor will generate a correct implementation.", e);
      // These exceptions can't be squashed across all versions of Android.
    } catch (IllegalAccessException e) {
      throw new IllegalStateException("GeneratedAppGlideModuleImpl is implemented incorrectly."
          + " If you've manually implemented this class, remove your implementation. The Annotation"
          + " processor will generate a correct implementation.", e);
    }
    return result;
  }
    
  ...
}

可以看到根据Class文件名反射生成GeneratedAppGlideModuleImpl实例,这个类就是通过注解编译器在项目

编译阶段生成的.Java文件,如下图:     

Android 学习使用annotationprocessor自动生成java文件 

http://blog.csdn.net/msn465780/article/details/78888668

Android 图片加载框架Glide主流程源码分析_第1张图片

可能有个疑问如果改缓存配置难道要在这个自动生成的类中改吗?肯定不会了,下面看下这个类,

@SuppressWarnings("deprecation")
final class GeneratedAppGlideModuleImpl extends GeneratedAppGlideModule {
  private final ImgurGlideModule appGlideModule;

  GeneratedAppGlideModuleImpl() {
    appGlideModule = new ImgurGlideModule();
    if (Log.isLoggable("Glide", Log.DEBUG)) {
      Log.d("Glide", "Discovered AppGlideModule from annotation: com.bumptech.glide.samples.imgur.ImgurGlideModule");
    }
  }

  @Override
  public void applyOptions(Context context, GlideBuilder builder) {
    appGlideModule.applyOptions(context, builder);
  }

  @Override
  public void registerComponents(Context context, Glide glide, Registry registry) {
    appGlideModule.registerComponents(context, glide, registry);
  }

  @Override
  public boolean isManifestParsingEnabled() {
    return appGlideModule.isManifestParsingEnabled();
  }

  @Override
  public Set> getExcludedModuleClasses() {
    return Collections.emptySet();
  }
   ...
}
第6行,看到了吗?构造了一个ImgurGlideModule实例,里面所有需要开发这定义的方法都实际是这个实例去干的,所以具体的配置都应该在ImgurGlideModule里面操作,这个GlideModule其实就是4.0以前我们需要重写的那个,类名是根据主Module名生成的。

接着我们回到Glide的构造那,可能之前的都忘记了,这里我再贴下那串很长的代码,

public class Glide implements ComponentCallbacks2 {
  ...
  @SuppressWarnings("deprecation")
  private static void initializeGlide(Context context, GlideBuilder builder) {
    // 初始化Glide
    Context applicationContext = context.getApplicationContext();
    // 获取GeneratedAppGlideModule的实例
    GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
    List manifestModules = Collections.emptyList();
    if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
      // 解析AndroidManifest.xml,把配置的自定义的GlideModule的实例保存到list中
      // 
      // 
      manifestModules = new ManifestParser(applicationContext).parse();
    }

    if (annotationGeneratedModule != null
        && !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
      // 这里有个疑问,annotationGeneratedModule.getExcludedModuleClasses()永远都是空的,根本不会执行下面的代码
      // 不知道这里加上这句判断有何作用
      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) {
      // 不在AndroidManifest.xml里面配置GlideModule,这个for进不来的,默认是不用配置的
      module.applyOptions(applicationContext, builder);
    }
    if (annotationGeneratedModule != null) {
      // 最新的glide4.0以上版本已经不再需要在AndroidManifest.xml中配置GlideModule;
      // applyOptions 是给自定义配置的,比如内存占比等,默认已经配置过
      annotationGeneratedModule.applyOptions(applicationContext, builder);
    }
    // 开始初始化Glide单例
    Glide glide = builder.build(applicationContext);
    // registerComponents 留给自定义的回调函数
    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;
  }  
  ...
}
第57行,生成Glide实例,Glide中用了大量的bulder模式、工厂模式,里面详细的代码下一篇介绍,主要是初始化内存缓存磁盘缓存相关的,第66行,返回的glide实例赋值给成员变量glide,到这里Glide单例就构建成功了,这里注意43-36行,一个工厂模式,干嘛的呢?其实就是用于生成GlideRequests实例的前置铺垫,创建一个GeneratedRequestManagerFactory,这个一看前缀就知道是自动生成的.java文件,与之前GeneratedAppGlideModuleImpl原理一样,代码如下:
final class GeneratedAppGlideModuleImpl extends GeneratedAppGlideModule {
  private final ImgurGlideModule appGlideModule;

  ...
  @Override
  GeneratedRequestManagerFactory getRequestManagerFactory() {
    return new GeneratedRequestManagerFactory();
  }
}
看到被生成的代码了吧,详细的就具体分析了,不然这篇文章得非常长,这里知道这个就可以了,然后回到开始这段代码,
public class Glide implements ComponentCallbacks2 {

  ...
  public static RequestManager with(View view) {
    return getRetriever(view.getContext()).get(view);
  }
    
}
get一个RequestManagerRetriever实例,接着根据传入的view继续get   RequestManager对象,跟踪进入,
public class RequestManagerRetriever implements Handler.Callback {

  ...
   public RequestManager get(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());
    // The view might be somewhere else, like a service.
    if (activity == null) {
      return get(view.getContext().getApplicationContext());
    }

    // Support Fragments.
    // Although the user might have non-support Fragments attached to FragmentActivity, searching
    // for non-support Fragments is so expensive pre O and that should be rare enough that we
    // prefer to just fall back to the Activity directly.
    if (activity instanceof FragmentActivity) {
      Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
      return fragment != null ? get(fragment) : get(activity);
    }

    // Standard Fragments.
    android.app.Fragment fragment = findFragment(view, activity);
    if (fragment == null) {
      return get(activity);
    }
    return get(fragment);
  }

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

  private RequestManager supportFragmentGet(Context context, FragmentManager fm,
      Fragment parentHint) {
    SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);
    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;
  }
... 
}
假设加载环境是Fragment,Activity同理,现在的APP基本都是用的Fragment

52-58行,54行成员变量factory其实就是刚才说的GeneratedRequestManagerFactory实例,也就是构造Glide实例时创建的,

因此,factory.build() 其实就是GeneratedRequestManagerFactory.build(),返回GlideRequests实例

final class GeneratedRequestManagerFactory implements RequestManagerRetriever.RequestManagerFactory {
  @Override
  public RequestManager build(Glide glide, Lifecycle lifecycle, RequestManagerTreeNode treeNode,
      Context context) {
    return new GlideRequests(glide, lifecycle, treeNode, context);
  }
}
也就是Glide.with(view) 返回了 GlideRequests实例


接下来看GlideRequests.load()


public class GlideRequests extends RequestManager {
  ...
  
    @Override
  @CheckResult
  public GlideRequest load(@Nullable String arg0) {
    return (GlideRequest) super.load(arg0);
  }
    
  ...
}
public class RequestManager implements LifecycleListener,
    ModelTypes> 
  ...
  
  /**
   * 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.
   */
  @CheckResult
  @Override
  public RequestBuilder load(@Nullable String string) {
    return asDrawable().load(string);
  }
    
  ...
}

先看13行,asDrawable(),

public class RequestManager implements LifecycleListener,
    ModelTypes> {
  ...
  
  @CheckResult
  public RequestBuilder asDrawable() {
    return as(Drawable.class);
  }

    @CheckResult
  public  RequestBuilder as(Class resourceClass) {
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }
    
  ...
}
这里需要注意,resourceClass 是Drawable.class 实例,记住,后面会有用,继续跟踪,
public class RequestBuilder implements Cloneable,
    ModelTypes> {
  ...
  
   protected RequestBuilder(Glide glide, RequestManager requestManager,
      Class transcodeClass, Context context) {
    this.glide = glide;
    this.requestManager = requestManager;
    this.transcodeClass = transcodeClass;
    this.defaultRequestOptions = requestManager.getDefaultRequestOptions();
    this.context = context;
    this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass);
    this.requestOptions = defaultRequestOptions;
    this.glideContext = glide.getGlideContext();
  }
  ...
}
构造了一个RequestBuilder实例,传入的参数赋值到RequestBuilder的成员变量,这里成员transcodeClass也就是刚才的Drawable.class,记住了,初始化了一个requestOptions,这2个成员记住了,后面会有用的,接着回到之前的一段代码,
public class RequestManager implements LifecycleListener,
    ModelTypes> {
  ...
  
    @CheckResult
  @Override
  public RequestBuilder load(@Nullable String string) {
    return asDrawable().load(string);
  }
  ...
}

现在跟踪load(string),

public class RequestBuilder implements Cloneable,
    ModelTypes> {
  ...
  
  @Override
  @CheckResult
  public RequestBuilder load(@Nullable String string) {
    return loadGeneric(string);
  }

  private RequestBuilder loadGeneric(@Nullable Object model) {
    this.model = model;
    isModelSet = true;
    return this;
  }
  ...
}
第12行,这个model当前是图片url String的实例,赋值给RequestBuilder成员,这里记住了,后面的分析model都是图片url地址,刚才赋值了2个重要参数  transcodeClass、defaultRequestOptions,后面会用到,到这里load()步骤就完毕了


接着看最复杂的GlideRequest.into(),

由于GlideRequest继承RequestBuilder,自己又没重写into()方法,因此这个into()是在RequestBuilder里面的,

public class RequestBuilder implements Cloneable,
    ModelTypes> {
  ...
  
    /**
   * 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.
   *
   * @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}.
   * @see RequestManager#clear(Target)
   */
  public ViewTarget into(ImageView view) {
    // 以下必须在主线程中执行,否则抛出异常
    Util.assertMainThread();
    Preconditions.checkNotNull(view);

    RequestOptions requestOptions = this.requestOptions;
    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);
  }
  ...
}
switch语句用于判断图片显示的模式,默认是CENTER_CROP,

49-53行,调用3个参数的into(),

第50行,根据之前提到的transcodeClass生成Target,Target是不是看起来很熟悉,我们继续跟踪,

public class GlideContext extends ContextWrapper {
  ...

  public  ViewTarget buildImageViewTarget(
    ImageView imageView, Class transcodeClass) {
    return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
  }

  ...
}
/**
 * A factory responsible for producing the correct type of
 * {@link com.bumptech.glide.request.target.Target} for a given {@link android.view.View} subclass.
 */
public class ImageViewTargetFactory {

  @SuppressWarnings("unchecked")
  public  ViewTarget buildTarget(ImageView view, Class clazz) {
    if (Bitmap.class.equals(clazz)) {
      return (ViewTarget) new BitmapImageViewTarget(view);
    } else if (Drawable.class.isAssignableFrom(clazz)) {
      return (ViewTarget) new DrawableImageViewTarget(view);
    } else {
      throw new IllegalArgumentException(
          "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
    }
  }
}
这里的clazz就是刚才传过来的transcodeClass,这个呢之前记住过,在分析的例子里是Drawable.class,很明显了,进入

第12行,创建返回DrawableImageViewTarget实例,这里也要记住了,以后的target就是DrawableImageViewTarget实例,

接着返回RequestBuilder

public class RequestBuilder implements Cloneable,
    ModelTypes> {
  ...

  public ViewTarget into(ImageView view) {
    // 以下必须在主线程中执行,否则抛出异常
    Util.assertMainThread();
    Preconditions.checkNotNull(view);
     ...

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

  ...
}
继续跟踪,
public class RequestBuilder implements Cloneable,
    ModelTypes> {
  ...
  private > Y into(
      @NonNull Y target,
      @Nullable RequestListener targetListener,
      RequestOptions options) {
    // 不为主线程就抛出异常
    Util.assertMainThread();
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

    options = options.autoClone();
    // 返回SingleRequest实例
    Request request = buildRequest(target, targetListener, options);

    // target从成员变量view中获取tag,这个tag是Request实例
    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;
  }

  ...
}
这里把之前生成的2个参数传入了过来, DrawableImageViewTarget,requestOptions,

第17行会返回Request实例,其实是SingleRequest的实例,为啥是它的实例呢,这里得跟踪进入,不然32行begin()就会不知道到底是哪个Request调用的

public class RequestBuilder implements Cloneable,
    ModelTypes> {
  ...
   private Request buildRequest(
      Target target,
      @Nullable RequestListener targetListener,
      RequestOptions requestOptions) {
    return buildRequestRecursive(
        target,
        targetListener,
        /*parentCoordinator=*/ null,
        transitionOptions,
        requestOptions.getPriority(),
        requestOptions.getOverrideWidth(),
        requestOptions.getOverrideHeight(),
        requestOptions);
  }

  private Request buildRequestRecursive(
      Target target,
      @Nullable RequestListener targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      RequestOptions requestOptions) {

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

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

   ...
  }

  ...
}

30-40行为主流程,继续跟踪,

public class RequestBuilder implements Cloneable,
    ModelTypes> {
  ...
  
    private Request buildThumbnailRequestRecursive(
      Target target,
      RequestListener targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      RequestOptions requestOptions) {
    if (thumbnailBuilder != null) {
      ...

      ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
      Request fullRequest =
          obtainRequest(
              target,
              targetListener,
              requestOptions,
              coordinator,
              transitionOptions,
              priority,
              overrideWidth,
              overrideHeight);
      isThumbnailBuilt = true;
      // Recursively generate thumbnail requests.
      Request thumbRequest =
          thumbnailBuilder.buildRequestRecursive(
              target,
              targetListener,
              coordinator,
              thumbTransitionOptions,
              thumbPriority,
              thumbOverrideWidth,
              thumbOverrideHeight,
              thumbnailBuilder.requestOptions);
      isThumbnailBuilt = false;
      coordinator.setRequests(fullRequest, thumbRequest);
      return coordinator;
    } else if (thumbSizeMultiplier != null) {
      // Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
      ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
      Request fullRequest =
          obtainRequest(
              target,
              targetListener,
              requestOptions,
              coordinator,
              transitionOptions,
              priority,
              overrideWidth,
              overrideHeight);
      RequestOptions thumbnailOptions = requestOptions.clone()
          .sizeMultiplier(thumbSizeMultiplier);

      Request thumbnailRequest =
          obtainRequest(
              target,
              targetListener,
              thumbnailOptions,
              coordinator,
              transitionOptions,
              getThumbnailPriority(priority),
              overrideWidth,
              overrideHeight);

      coordinator.setRequests(fullRequest, thumbnailRequest);
      return coordinator;
    } else {
      // Base case: no thumbnail.
      return obtainRequest(
          target,
          targetListener,
          requestOptions,
          parentCoordinator,
          transitionOptions,
          priority,
          overrideWidth,
          overrideHeight);
    }
  }

  ...
}

这个方法也挺长的,因为只研究网络图片加载的主流程,很多详细的地方就不描述了,第一次加载网络图片,会执行

74-83行,去构造这个Request实例,Request只是一个接口,实现它的有几个类,具体是哪个,我们继续跟踪,

答案即将揭晓

public class RequestBuilder implements Cloneable,
    ModelTypes> {
  ...
  private Request obtainRequest(
      Target target,
      RequestListener targetListener,
      RequestOptions requestOptions,
      RequestCoordinator requestCoordinator,
      TransitionOptions transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight) {
    return SingleRequest.obtain(
        context,
        glideContext,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListener,
        requestCoordinator,
        glideContext.getEngine(),
        transitionOptions.getTransitionFactory());
  }

  ...
}

看到了吧,SingleRequest.obtain()去构造了SingleRequest实例并返回,我们也返回,

public class RequestBuilder implements Cloneable,
    ModelTypes> {
  ...
  private > Y into(
      @NonNull Y target,
      @Nullable RequestListener targetListener,
      RequestOptions options) {
    // 不为主线程就抛出异常
    Util.assertMainThread();
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

    options = options.autoClone();
    // 返回SingleRequest实例
    Request request = buildRequest(target, targetListener, options);

    // target从成员变量view中获取tag,这个tag是Request实例
    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;
  }

  ...
}

经过这些操作后32行,调用begin(),也就是SingleRequest.begin(),接着看到这个方法,好戏正上演

public final class SingleRequest implements Request,
    SizeReadyCallback,
    ResourceCallback,
    FactoryPools.Poolable {
  ...
   @Override
  public void begin() {
    assertNotCallingCallbacks();
    stateVerifier.throwIfRecycled();
    startTime = LogTime.getLogTime();
    if (model == null) {
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
        // 不调用glide.override(),
        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 {
      // 父类ViewTarget的getSize(),调用onSizeReady();
      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));
    }
  }

  ...
}

11行,判断了model是否为null,model前面提过,在这篇文章里就是url地址,String类型,肯定不为空,所以跳过,

34-37行,这个是图片是否加载完成,加载完成后onResourceReady()回调函数,这类型的回调函数Glide用得很多,加载好的图片资源会一层一层的回调到Target去让ImageView显示,这里由于是第一次加载,所以跳过

42-48行,overrideWidth、overrideHeight是个啥呢,记得GlideRequest.override(int overrideWidth, int overrideHeight),如果不设置这个,Glide是用的控件的尺寸来计算图片的缩放比例的,设置这个后,就会根据我们提供的宽高去计算图片的缩放比例,由于这篇文章没有设置,那就是默认的,因此跳过

47行,target,哈哈,又见到它了吧,前提反复提过,还记得起吧,这篇文章的是DrawableImageViewTarget实例,我们去看

getSize(),发现没有,对吧,说明这个方法是父类或者爷爷等类中描述的,最终找到在ViewTarget里面

public abstract class ViewTarget extends BaseTarget {
  ...
  @CallSuper
  @Override
  public void getSize(SizeReadyCallback cb) {
    sizeDeterminer.getSize(cb);
  }

    @VisibleForTesting
  static final class SizeDeterminer {
  ...
  
   void getSize(SizeReadyCallback cb) {
      // 计算控件的宽高
      int currentWidth = getTargetWidth();
      int currentHeight = getTargetHeight();
      if (isViewStateAndSizeValid(currentWidth, currentHeight)) {
        cb.onSizeReady(currentWidth, currentHeight);
        return;
      }

      // We want to notify callbacks in the order they were added and we only expect one or two
      // callbacks to be added a time, so a List is a reasonable choice.
      if (!cbs.contains(cb)) {
        cbs.add(cb);
      }
      if (layoutListener == null) {
        ViewTreeObserver observer = view.getViewTreeObserver();
        layoutListener = new SizeDeterminerLayoutListener(this);
        observer.addOnPreDrawListener(layoutListener);
      }
    }
    
  ...
}
  ...
}

还记得这里的cb是啥吗,也就是SingleRequest实例,这个cb的好几处都用到了,说白了就是后面需要进行回调,这里先有点印象先,18行,主流程,然后回到SingleRequest.onSizeReady()

public final class SingleRequest implements Request,
    SizeReadyCallback,
    ResourceCallback,
    FactoryPools.Poolable {
  ...
  /**
   * A callback method that should never be invoked directly.
   */
  @Override
  public 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));
    }
    // 构建Engine实例,整个加载过程的管理器
    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);

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

  ...
}

28行开始正式进入加载主题了,engine.load(),首先来看下engine是什么,这个对象其实就是整个加载流程的引擎,在哪被构造出来的呢,还记得构造Glide实例那里的代码吗

public class Glide implements ComponentCallbacks2 {
  ...
 
   @SuppressWarnings("deprecation")
  private static void initializeGlide(Context context, GlideBuilder builder) {
  ...
    // 开始初始化Glide单例
    Glide glide = builder.build(applicationContext);
    ...
    Glide.glide = glide;
  }

  ...
}
public final class GlideBuilder {
  ...
 
   public Glide build(Context context) {
   ...

    if (engine == null) {
      engine =
          new Engine(
              memoryCache,
              diskCacheFactory,
              diskCacheExecutor,
              sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor(),
              GlideExecutor.newAnimationExecutor(),
              isActiveResourceRetentionAllowed);
    }

    RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory);

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

  ...
}

明白了吧,在构造Glide单例的时候构造了Engine实例,继续跟踪

public class Glide implements ComponentCallbacks2 {
  ...
 
   public Glide build(Context context) {
   ...

  Glide(
      Context context,
      Engine engine,
      MemoryCache memoryCache,
      BitmapPool bitmapPool,
      ArrayPool arrayPool,
      RequestManagerRetriever requestManagerRetriever,
      ConnectivityMonitorFactory connectivityMonitorFactory,
      int logLevel,
      RequestOptions defaultRequestOptions,
      Map, TransitionOptions> defaultTransitionOptions) {
    this.engine = engine;
    this.bitmapPool = bitmapPool;
    this.arrayPool = arrayPool;
    this.memoryCache = memoryCache;
    this.requestManagerRetriever = requestManagerRetriever;
    this.connectivityMonitorFactory = connectivityMonitorFactory;

    DecodeFormat decodeFormat = defaultRequestOptions.getOptions().get(Downsampler.DECODE_FORMAT);
    bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat);

    final Resources resources = context.getResources();

    registry = new Registry();
    registry.register(new DefaultImageHeaderParser());

    Downsampler downsampler = new Downsampler(registry.getImageHeaderParsers(),
        resources.getDisplayMetrics(), bitmapPool, arrayPool);
    ByteBufferGifDecoder byteBufferGifDecoder =
        new ByteBufferGifDecoder(context, registry.getImageHeaderParsers(), bitmapPool, arrayPool);
    VideoBitmapDecoder videoBitmapDecoder = new VideoBitmapDecoder(bitmapPool);
    ByteBufferBitmapDecoder byteBufferBitmapDecoder = new ByteBufferBitmapDecoder(downsampler);
    StreamBitmapDecoder streamBitmapDecoder = new StreamBitmapDecoder(downsampler, arrayPool);
    ResourceDrawableDecoder resourceDrawableDecoder =
        new ResourceDrawableDecoder(context);
    ResourceLoader.StreamFactory resourceLoaderStreamFactory =
        new ResourceLoader.StreamFactory(resources);
    ResourceLoader.UriFactory resourceLoaderUriFactory =
        new ResourceLoader.UriFactory(resources);
    ResourceLoader.FileDescriptorFactory resourceLoaderFileDescriptorFactory =
        new ResourceLoader.FileDescriptorFactory(resources);
    BitmapEncoder bitmapEncoder = new BitmapEncoder();

    registry
        .append(ByteBuffer.class, new ByteBufferEncoder())
        .append(InputStream.class, new StreamEncoder(arrayPool))
        /* Bitmaps */
        .append(Registry.BUCKET_BITMAP, ByteBuffer.class, Bitmap.class, byteBufferBitmapDecoder)
        .append(Registry.BUCKET_BITMAP, InputStream.class, Bitmap.class, streamBitmapDecoder)
        .append(
            Registry.BUCKET_BITMAP, ParcelFileDescriptor.class, Bitmap.class, videoBitmapDecoder)
        .append(
            Registry.BUCKET_BITMAP, Bitmap.class, Bitmap.class, new UnitBitmapDecoder())
        .append(Bitmap.class, Bitmap.class, UnitModelLoader.Factory.getInstance())
        .append(Bitmap.class, bitmapEncoder)
        /* BitmapDrawables */
        .append(
            Registry.BUCKET_BITMAP_DRAWABLE,
            ByteBuffer.class,
            BitmapDrawable.class,
            new BitmapDrawableDecoder<>(resources, byteBufferBitmapDecoder))
        .append(
            Registry.BUCKET_BITMAP_DRAWABLE,
            InputStream.class,
            BitmapDrawable.class,
            new BitmapDrawableDecoder<>(resources, streamBitmapDecoder))
        .append(
            Registry.BUCKET_BITMAP_DRAWABLE,
            ParcelFileDescriptor.class,
            BitmapDrawable.class,
            new BitmapDrawableDecoder<>(resources, videoBitmapDecoder))
        .append(BitmapDrawable.class, new BitmapDrawableEncoder(bitmapPool, bitmapEncoder))
        /* GIFs */
        .append(
            Registry.BUCKET_GIF,
            InputStream.class,
            GifDrawable.class,
            new StreamGifDecoder(registry.getImageHeaderParsers(), byteBufferGifDecoder, arrayPool))
        .append(Registry.BUCKET_GIF, ByteBuffer.class, GifDrawable.class, byteBufferGifDecoder)
        .append(GifDrawable.class, new GifDrawableEncoder())
        /* GIF Frames */
        // Compilation with Gradle requires the type to be specified for UnitModelLoader here.
        .append(
            GifDecoder.class, GifDecoder.class, UnitModelLoader.Factory.getInstance())
        .append(
            Registry.BUCKET_BITMAP,
            GifDecoder.class,
            Bitmap.class,
            new GifFrameResourceDecoder(bitmapPool))
        /* Drawables */
        .append(Uri.class, Drawable.class, resourceDrawableDecoder)
        .append(
            Uri.class, Bitmap.class, new ResourceBitmapDecoder(resourceDrawableDecoder, bitmapPool))
        /* Files */
        .register(new ByteBufferRewinder.Factory())
        .append(File.class, ByteBuffer.class, new ByteBufferFileLoader.Factory())
        .append(File.class, InputStream.class, new FileLoader.StreamFactory())
        .append(File.class, File.class, new FileDecoder())
        .append(File.class, ParcelFileDescriptor.class, new FileLoader.FileDescriptorFactory())
        // Compilation with Gradle requires the type to be specified for UnitModelLoader here.
        .append(File.class, File.class, UnitModelLoader.Factory.getInstance())
        /* Models */
        .register(new InputStreamRewinder.Factory(arrayPool))
        .append(int.class, InputStream.class, resourceLoaderStreamFactory)
        .append(
                int.class,
                ParcelFileDescriptor.class,
                resourceLoaderFileDescriptorFactory)
        .append(Integer.class, InputStream.class, resourceLoaderStreamFactory)
        .append(
                Integer.class,
                ParcelFileDescriptor.class,
                resourceLoaderFileDescriptorFactory)
        .append(Integer.class, Uri.class, resourceLoaderUriFactory)
        .append(int.class, Uri.class, resourceLoaderUriFactory)
        .append(String.class, InputStream.class, new DataUrlLoader.StreamFactory())
        .append(String.class, InputStream.class, new StringLoader.StreamFactory())
        .append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())
        .append(Uri.class, InputStream.class, new HttpUriLoader.Factory())
        .append(Uri.class, InputStream.class, new AssetUriLoader.StreamFactory(context.getAssets()))
        .append(
                Uri.class,
                ParcelFileDescriptor.class,
                new AssetUriLoader.FileDescriptorFactory(context.getAssets()))
        .append(Uri.class, InputStream.class, new MediaStoreImageThumbLoader.Factory(context))
        .append(Uri.class, InputStream.class, new MediaStoreVideoThumbLoader.Factory(context))
        .append(
            Uri.class,
            InputStream.class,
            new UriLoader.StreamFactory(context.getContentResolver()))
        .append(Uri.class, ParcelFileDescriptor.class,
             new UriLoader.FileDescriptorFactory(context.getContentResolver()))
        .append(Uri.class, InputStream.class, new UrlUriLoader.StreamFactory())
        .append(URL.class, InputStream.class, new UrlLoader.StreamFactory())
        .append(Uri.class, File.class, new MediaStoreFileLoader.Factory(context))
        .append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())
        .append(byte[].class, ByteBuffer.class, new ByteArrayLoader.ByteBufferFactory())
        .append(byte[].class, InputStream.class, new ByteArrayLoader.StreamFactory())
        .append(Uri.class, Uri.class, UnitModelLoader.Factory.getInstance())
        .append(Drawable.class, Drawable.class, UnitModelLoader.Factory.getInstance())
        .append(Drawable.class, Drawable.class, new UnitDrawableDecoder())
        /* Transcoders */
        .register(
            Bitmap.class,
            BitmapDrawable.class,
            new BitmapDrawableTranscoder(resources))
        .register(Bitmap.class, byte[].class, new BitmapBytesTranscoder())
        .register(GifDrawable.class, byte[].class, new GifDrawableBytesTranscoder());

    ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
    glideContext =
        new GlideContext(
            context,
            arrayPool,
            registry,
            imageViewTargetFactory,
            defaultRequestOptions,
            defaultTransitionOptions,
            engine,
            logLevel);
  }

  ...
}

Glide的构造方法真长,这里为啥要都贴出来,是有原因的

157-167行,构造GlideContext实例,engine实例作为它的成员变量,

50-155行,registry实例在append数据,这里可是一个大伏笔,特别注意122-124行,这里是本篇文章后面分析要用到的

现在回到Engine.load(),接着上面继续看

public class Engine implements EngineJobListener,
    MemoryCache.ResourceRemovedListener,
    EngineResource.ResourceListener {
  ...
 
   public  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) {
    Util.assertMainThread();
    long startTime = LogTime.getLogTime();

    // 根据各种参数创建图片key
    EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
        resourceClass, transcodeClass, options);

    // 检查内存中弱引用是否有目标图片
    EngineResource active = loadFromActiveResources(key, isMemoryCacheable);
    if (active != null) {
      cb.onResourceReady(active, DataSource.MEMORY_CACHE);
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        logWithTimeAndKey("Loaded resource from active resources", startTime, key);
      }
      return null;
    }

    // 检查内存中Lrucache是否有目标图片
    EngineResource cached = loadFromCache(key, isMemoryCacheable);
    if (cached != null) {
      cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        logWithTimeAndKey("Loaded resource from cache", startTime, key);
      }
      return null;
    }

    // 内存中没有图片往下执行
    EngineJob current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
      current.addCallback(cb);
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        logWithTimeAndKey("Added to existing load", startTime, key);
      }
      return new LoadStatus(cb, current);
    }

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

    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);
    engineJob.start(decodeJob);

    if (Log.isLoggable(TAG, Log.VERBOSE)) {
      logWithTimeAndKey("Started new load", startTime, key);
    }
    return new LoadStatus(cb, engineJob);
  }

  ...
}

这段代码也很长,我们从62行开始看,因为前面的代码都是关于缓存中已经有目标图片了,直接出来回调,由于本片文章是关于第一次网络加载,所以缓存部分暂时不过多描述

这里出现了2个类,非常重要,EngineJob、DecodeJob ,EngineJob相当于线程池,DecodeJob就是一个实现Runnable的任务,所以加载的具体业务都在DecodeJob中

92行,这里又是回调,我们要知道cb是啥,这里是SingleRequest实例,也是一级一级传过来的,作用还是待会图片加载好了传到target显示

93行,开启异步加载任务

class EngineJob implements DecodeJob.Callback,
    Poolable {
  ...
   public void start(DecodeJob decodeJob) {
    this.decodeJob = decodeJob;
    GlideExecutor executor = decodeJob.willDecodeFromCache()
        ? diskCacheExecutor
        : getActiveSourceExecutor();
    executor.execute(decodeJob);
  }

  ...
}

这里用的是GlideExecutor实例去加载,这里先不要管这个实例在哪构造的,就是一个线程池去开启了DecodeJob,接下来跟踪DecodeJob的run()方法

class DecodeJob implements DataFetcherGenerator.FetcherReadyCallback,
    Runnable,
    Comparable>,
    Poolable {
  ...
   @Override
  public void run() {
    ...
    try {
      if (isCancelled) {
        notifyFailed();
        return;
      }
      // 主流程代码
      runWrapped();
    } catch (Throwable t) {
      ...
    } 
      TraceCompat.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);
    }
  }
  ...
}
24-35行,这里就是分步骤去相应的DataFetcherGenerator实例中去加载图片资源
class DecodeJob implements DataFetcherGenerator.FetcherReadyCallback,
    Runnable,
    Comparable>,
    Poolable {
  ...
  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);
    }
  }
  ...
}

getNextGenerator(),用于计算当前加载处于哪一步,并返回相应的DataFetcherGenerator,

ResourceCacheGenerator 表示磁盘缓存图片资源,

DataCacheGenerator 表示磁盘处理后的缓存图片资源,

SourceGenerator 表示原始图片资源,

这里是第一次加载,所以缓存不存在,会返回SourceGenerator 实例,循环几次调用runGenerators(),当最后一次调用runGenerators()时,才是真正去加载图片

class DecodeJob implements DataFetcherGenerator.FetcherReadyCallback,
    Runnable,
    Comparable>,
    Poolable {
  ...
 
   private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    // startNext()里面加载图片
    while (!isCancelled && currentGenerator != null
        && !(isStarted = currentGenerator.startNext())) {
      stage = getNextStage(stage);
      currentGenerator = getNextGenerator();

      if (stage == Stage.SOURCE) {
        // 无缓存,再次执行run()
        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.
  }
  ...
}

13行,这里就是去加载,currentGenerator.startNext(),DataFetcherGenerator接口定义了这么一个startNext()方法,它的实现类扩展这个方法,都是去加载图片的意思,不管是缓存图片还是网络图片

15-20行,用于获取加载步骤

24-26行,如果状态发生变化需要取消,就通知取消加载,最外面一层回调为加载失败

现在已经知道加载是SourceGenerator.startNext(),继续跟踪

class SourceGenerator implements DataFetcherGenerator,
    DataFetcher.DataCallback,
    DataFetcherGenerator.FetcherReadyCallback {
  ...
 
  SourceGenerator(DecodeHelper helper, FetcherReadyCallback cb) {
    this.helper = helper;
    this.cb = cb;
  }

  @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;
        // 实际发起请求的地方
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }
    return started;
  }

  ...
} 
  

33行,我已经标出了实际发起网络请求的地方,这里fetcher.loadData(),直接进入之能查看到接口DataFetcher定义的

loadData(),DataFatcher的实现类相当多,到底用的哪个呢

Android 图片加载框架Glide主流程源码分析_第2张图片

我们可以猜一下,从命名字面上看OKhttpStreamFetcher、HttpUrlFetcher最有可能,又想下,Glide加载不一定就是用的OKhttp,所以HttpUrlFetcher最有可能,确实是的,但是为啥是它呢,一路过来也没看到哪构造了它的实例呢?

这里要知道它是怎么被构造出来的,逻辑也挺复杂的,不过没事,再复杂的逻辑也是一点点简单的逻辑堆起来的,还记得前面提到的构造Glide单例吗,

public class Glide implements ComponentCallbacks2 {
  ...
 
  Glide(
      Context context,
      Engine engine,
      MemoryCache memoryCache,
      BitmapPool bitmapPool,
      ArrayPool arrayPool,
      RequestManagerRetriever requestManagerRetriever,
      ConnectivityMonitorFactory connectivityMonitorFactory,
      int logLevel,
      RequestOptions defaultRequestOptions,
      Map, TransitionOptions> defaultTransitionOptions) {
    ...

    registry = new Registry();
    registry.register(new DefaultImageHeaderParser());
    ...

    registry
        .append(ByteBuffer.class, new ByteBufferEncoder())
        ...
        
        /* GIF Frames */
        // Compilation with Gradle requires the type to be specified for UnitModelLoader here.
        ...
        .append(String.class, InputStream.class, new DataUrlLoader.StreamFactory())
        .append(String.class, InputStream.class, new StringLoader.StreamFactory())
        .append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())
        .append(Uri.class, InputStream.class, new HttpUriLoader.Factory())
        .append(Uri.class, InputStream.class, new AssetUriLoader.StreamFactory(context.getAssets()))
        .append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())
        ...
        /* Transcoders */
        .register(
            Bitmap.class,
            BitmapDrawable.class,
            new BitmapDrawableTranscoder(resources))
        .register(Bitmap.class, byte[].class, new BitmapBytesTranscoder())
        .register(GifDrawable.class, byte[].class, new GifDrawableBytesTranscoder());
	...
  }

  ...
}

Registry实例apend很多数据类型,这里是一个大铺垫,目的就是为了以后加载图片资源是选择相应的Factory来构造相应的DataFetcher,上面我留下来的都是跟Url相关的,到底是哪个append呢?

再次回到SourceGenerator

class SourceGenerator implements DataFetcherGenerator,
    DataFetcher.DataCallback,
    DataFetcherGenerator.FetcherReadyCallback {
  ...
 
  @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;
        // 实际发起请求的地方
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }
    return started;
  }


  ...
} 
  

28行,我们知道fetcher是loadData中获取的,loadData呢?

22行,获取到了loadData实例,跟踪进入

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

第8行,从Registry中获取到一个ModelLoader的集合,Registry实例也就是刚才Glide构造里面那个实例,赋值给glideContext成员变量

第13行,根据获取到的ModelLoader集合遍历调用buildLoadData(),构造出一个LoadData的实例,这里可能会构造出多个实例,因为ModelLoader接口的实现类很多,谁知道Registry返回哪些实现类呢,

最后方法吧构造出来的LoadData的实例集合返回

现在跟踪第8行,

public class Registry {
  ...
 
  public  List> getModelLoaders(Model model) {
    List> result = modelLoaderRegistry.getModelLoaders(model);
    if (result.isEmpty()) {
      throw new NoModelLoaderAvailableException(model);
    }
    return result;
  }
  ...
}

这里又出现Model,前面也提到过,model实例这篇文章中永远都是URL  String

// Hides Model throughout.
@SuppressWarnings("TypeParameterHidesVisibleType")
public class ModelLoaderRegistry {
  ...
 
  public synchronized  List> getModelLoaders(A model) {
    List> modelLoaders = getModelLoadersForClass(getClass(model));
    int size = modelLoaders.size();
    List> filteredLoaders = new ArrayList<>(size);
    for (int i = 0; i < size; i++) {
      ModelLoader loader = modelLoaders.get(i);
      if (loader.handles(model)) {
        filteredLoaders.add(loader);
      }
    }
    return filteredLoaders;
  }
  ...
}

我们是要获取ModerLoader的集合,这里跟踪第7行

// Hides Model throughout.
@SuppressWarnings("TypeParameterHidesVisibleType")
public class ModelLoaderRegistry {
  ...
 
  private  List> getModelLoadersForClass(Class modelClass) {
    List> loaders = cache.get(modelClass);
    if (loaders == null) {
      loaders = Collections.unmodifiableList(multiModelLoaderFactory.build(modelClass));
      cache.put(modelClass, loaders);
    }
    return loaders;
  }
  ...
}

cache与本次主流程无关,跳过,直接跟踪multiModelLoaderFactory.build(modelClass)

// Hides Model throughout.
public class MultiModelLoaderFactory {
  ...
  synchronized  List> build(Class modelClass) {
    try {
      List> loaders = new ArrayList<>();
      for (Entry entry : entries) {
        // Avoid stack overflow recursively creating model loaders by only creating loaders in
        // recursive requests if they haven't been created earlier in the chain. For example:
        // A Uri loader may translate to another model, which in turn may translate back to a Uri.
        // The original Uri loader won't be provided to the intermediate model loader, although
        // other Uri loaders will be.
        if (alreadyUsedEntries.contains(entry)) {
          continue;
        }
        if (entry.handles(modelClass)) {
          alreadyUsedEntries.add(entry);
          loaders.add(this.build(entry));
          alreadyUsedEntries.remove(entry);
        }
      }
      return loaders;
    } catch (Throwable t) {
      alreadyUsedEntries.clear();
      throw t;
    }
  }

    @SuppressWarnings("unchecked")
  private  ModelLoader build(Entry entry) {
    return (ModelLoader) Preconditions.checkNotNull(entry.factory.build(this));
  }
  ...
}

第7行,出现了一个容器entries,遍历

第18行,遍历出来的Entry实例调用了自己的build()方法,构造出了ModelLoader实例,新容器add后返回,也就是前面需要的ModelLoader实例的集合

现在我们需要知道的entries是啥,Entry是啥,不然这里就短路了

其实跟Registry有关,这里可以透露下,Entry是一个实体,包含了3个重要成员变量,哈哈,先从Registry.append()开始看吧

还记得起Registry吧

public class Registry {
  ...
  public  Registry append(Class modelClass, Class dataClass,
      ModelLoaderFactory factory) {
    modelLoaderRegistry.append(modelClass, dataClass, factory);
    return this;
  }
  ...
}

比如,append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory()),

传了3个参数进来modelClass、dataClass、factory,这3个都有用的,这里先注意下,再跟踪,

public class MultiModelLoaderFactory {
  ...
  synchronized  void append(
      Class modelClass,
      Class dataClass,
      ModelLoaderFactory factory) {
    add(modelClass, dataClass, factory, /*append=*/ true);
  }

    private  void add(
      Class modelClass,
      Class dataClass,
      ModelLoaderFactory factory,
      boolean append) {
    Entry entry = new Entry<>(modelClass, dataClass, factory);
    entries.add(append ? entries.size() : 0, entry);
  }
  ...
}

哈哈,是不是发现了前面短路的地方,又到了MultiModelLoaderFactory里面

15行,构造了一个Entry实例,把刚才传入的三个参数赋值为成员变量

16行,看到之前那个entries 了吧,它是一个集合,元素是Entry,然后把Entry实例添加

到这里应该明白了吧,然后返回前面获取ModelLoader集合的地方

public class MultiModelLoaderFactory {
  ...
  synchronized  List> build(Class modelClass) {
    try {
      List> loaders = new ArrayList<>();
      for (Entry entry : entries) {
        // Avoid stack overflow recursively creating model loaders by only creating loaders in
        // recursive requests if they haven't been created earlier in the chain. For example:
        // A Uri loader may translate to another model, which in turn may translate back to a Uri.
        // The original Uri loader won't be provided to the intermediate model loader, although
        // other Uri loaders will be.
        if (alreadyUsedEntries.contains(entry)) {
          continue;
        }
        if (entry.handles(modelClass)) {
          alreadyUsedEntries.add(entry);
          loaders.add(this.build(entry));
          alreadyUsedEntries.remove(entry);
        }
      }
      return loaders;
    } catch (Throwable t) {
      alreadyUsedEntries.clear();
      throw t;
    }
  }

    private static class Entry {
    private final Class modelClass;
    @Synthetic final Class dataClass;
    @Synthetic final ModelLoaderFactory factory;

    public Entry(
        Class modelClass,
        Class dataClass,
        ModelLoaderFactory factory) {
      this.modelClass = modelClass;
      this.dataClass = dataClass;
      this.factory = factory;
    }

    public boolean handles(Class modelClass, Class dataClass) {
      return handles(modelClass) && this.dataClass.isAssignableFrom(dataClass);
    }

    public boolean handles(Class modelClass) {
      return this.modelClass.isAssignableFrom(modelClass);
    }
  }
  ...
}

15行,遍历到的Entry实例调用handles(),用Entry实例成员变量modelClass和传入进来的modelClass进行比较,这篇文章凡是model实例都是url String,所以传入进来的modelClass也就是String.class,循环过后凡是String.class

执行17行代码,loaders.add(this.build(entry));

这里符合的也就只有这么几个

.append(String.class, InputStream.class, new DataUrlLoader.StreamFactory())
        .append(String.class, InputStream.class, new StringLoader.StreamFactory())
        .append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())

跟踪build(),

public class MultiModelLoaderFactory {
  ...
  @SuppressWarnings("unchecked")
  private  ModelLoader build(Entry entry) {
    return (ModelLoader) Preconditions.checkNotNull(entry.factory.build(this));
  }
  ...
}

entry.factory现在知道是啥了吧,就是上面的几个Factory,专门用来构造ModelLoader的实现类的,接下来又要开始复杂了,

我也想不通为啥Glide要搞那么复杂,最终结果不就是为了过滤出一个HttpUrlFetcher嘛,搞个简单的过滤不好吗,

先看下这2个ModelLoader的build()方法

public final class DataUrlLoader implements ModelLoader {
  ...
 public static final class StreamFactory implements ModelLoaderFactory {
    @Override
    public final ModelLoader build(MultiModelLoaderFactory multiFactory) {
      return new DataUrlLoader<>(opener);
    }
 }
  ...
}
public class StringLoader implements ModelLoader {
  ...
  public static class StreamFactory implements ModelLoaderFactory {
    @Override
    public ModelLoader build(MultiModelLoaderFactory multiFactory) {
      return new StringLoader<>(multiFactory.build(Uri.class, InputStream.class));
    }
  }
  ...
  public static class FileDescriptorFactory
      implements ModelLoaderFactory {

    @Override
    public ModelLoader build(MultiModelLoaderFactory multiFactory) {
      return new StringLoader<>(multiFactory.build(Uri.class, ParcelFileDescriptor.class));
    }
  }
  ...
}

DataUrlLoader比较简单直接构造了实例,StringLoader的Factory也构造了2个实例,不过

6行和15行,除了构造StringLoader实例外,还继续用传过来的MultiModelLoaderFactory实例继续build    modelLoader

作为自己的成员变量,接着跟踪MultiModelLoaderFactory.build,带有2个参数,参数的目的就是为了过滤的

public class MultiModelLoaderFactory {
  ...
  public synchronized  ModelLoader build(Class modelClass,
      Class dataClass) {
    try {
      List> loaders = new ArrayList<>();
      boolean ignoredAnyEntries = false;
      for (Entry entry : entries) {
        // Avoid stack overflow recursively creating model loaders by only creating loaders in
        // recursive requests if they haven't been created earlier in the chain. For example:
        // A Uri loader may translate to another model, which in turn may translate back to a Uri.
        // The original Uri loader won't be provided to the intermediate model loader, although
        // other Uri loaders will be.
        if (alreadyUsedEntries.contains(entry)) {
          ignoredAnyEntries = true;
          continue;
        }
        if (entry.handles(modelClass, dataClass)) {
          alreadyUsedEntries.add(entry);
          loaders.add(this.build(entry));
          alreadyUsedEntries.remove(entry);
        }
      }
      if (loaders.size() > 1) {
        return factory.build(loaders, throwableListPool);
      } else if (loaders.size() == 1) {
        return loaders.get(0);
      } else {
        // Avoid crashing if recursion results in no loaders available. The assertion is supposed to
        // catch completely unhandled types, recursion may mean a subtype isn't handled somewhere
        // down the stack, which is often ok.
        if (ignoredAnyEntries) {
          return emptyModelLoader();
        } else {
          throw new NoModelLoaderAvailableException(modelClass, dataClass);
        }
      }
    } catch (Throwable t) {
      alreadyUsedEntries.clear();
      throw t;
    }
  }
  ...
  static class Factory {
    public  MultiModelLoader build(
        List> modelLoaders, Pool> throwableListPool) {
      return new MultiModelLoader<>(modelLoaders, throwableListPool);
    }
  }
  ...
}

这个MultiModelLoaderFactory.build()跟之前的大概逻辑差不多,不过是2个参数的

18-22行,用参数过的参数entries中的Entry比较,如果符合就再调用Factory.build()去构造ModelLoader,再添加进ModLoader集合

24-28行,如果ModelLoader集合数量只有一个,就返回这一个ModerLoader,如果数量大于1,则调用45-47,构造一个

MultiModelLoader实例,把集合传入MultiModelLoader作为它的成员变量,通过Registry.append()可以知道数量都是

大于1,则之前构造的2个StringLoader实例的成员变量都会引用MultiModelLoader实例

意思就是最开始的的ModelLoader集合有3个实例,一个DataUrlLoader、2个StringLoader,

接下来回到ModelLoaderRegistry

public class ModelLoaderRegistry {
  ...
  public synchronized  List> getModelLoaders(A model) {
    List> modelLoaders = getModelLoadersForClass(getClass(model));
    int size = modelLoaders.size();
    List> filteredLoaders = new ArrayList<>(size);
    for (int i = 0; i < size; i++) {
      ModelLoader loader = modelLoaders.get(i);
      if (loader.handles(model)) {
        filteredLoaders.add(loader);
      }
    }
    return filteredLoaders;
  }  
  ...
}

第4行,我们此时可以知道返回的ModelLoader集合就是这3个ModelLoader的实例

第9行,遍历调用这几个ModelLoader实例的handles(),分别跟踪进入后可以知道DataUrlLoader不符合,所以目前

只剩下2个StringLoader实例,它们分别又持有MultiModelLoader实例

现在我们可以知道只有当2个参数的build()返回多个ModelLoader实例时,才会用到MultiModelLoader

接着继续返回,到DecodeHelper

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

看这个方法应该知道遍历ModelLoader集合,然后调用buildLoadData()得到一个LoadData实例,然后添加了LoadData集合

并返回

12行,这句是重点,由于已经知道返回的ModelLoader是StringLoader实例,跟踪进入

public class StringLoader implements ModelLoader {
  private final ModelLoader uriLoader;
  ...
  public StringLoader(ModelLoader uriLoader) {
    this.uriLoader = uriLoader;
  }

  @Override
  public LoadData buildLoadData(@NonNull String model, int width, int height,
      @NonNull Options options) {
    Uri uri = parseUri(model);
    return uri == null ? null : uriLoader.buildLoadData(uri, width, height, options);
  }
  ...
}

11行,model转为Uri的实例

12行,前面的分析,已经知道成员变量uriLoader其实就是MultiModelLoader的实例,接着跟踪buildLoadData()

class MultiModelLoader implements ModelLoader {
  ...
  @Override
  public LoadData buildLoadData(@NonNull Model model, int width, int height,
      @NonNull Options options) {
    Key sourceKey = null;
    int size = modelLoaders.size();
    List> fetchers = new ArrayList<>(size);
    for (int i = 0; i < size; i++) {
      ModelLoader modelLoader = modelLoaders.get(i);
      if (modelLoader.handles(model)) {
        LoadData loadData = modelLoader.buildLoadData(model, width, height, options);
        if (loadData != null) {
          sourceKey = loadData.sourceKey;
          fetchers.add(loadData.fetcher);
        }
      }
    }
    return !fetchers.isEmpty()
        ? new LoadData<>(sourceKey, new MultiFetcher<>(fetchers, exceptionListPool)) : null;
  }
  ...
}

这里需要注意了,之前一直提醒说Model是URL String,哈哈,不过这里刚才提到了,已经被转换为Uri了

6-18行,遍历从ModelLoader中得到DataFetcher实例,然后添加到DataFetcher集合中,这里需要注意,ModelLoader

不是StringLoader,因为目前其实还在StringLoader实例内部,ModelLoader集合是MultiModelLoader实例中

持有的,这里很绕,要仔细分清

11行,调用ModelLoader.handles(),又开始过滤,我感觉有点梦中梦的感觉了,哈哈,此时就要去看Registry.append(),

一个一个的去看,过滤后还剩哪几个ModelLoader实例,最后经过能活下来的ModelLoader只有

HttpUriLoader、UrlUriLoader

12行,modelLoader.buildLoadData()构造LoadData实例,分别跟踪这2个类

public class HttpUriLoader implements ModelLoader {
  private static final Set SCHEMES =
      Collections.unmodifiableSet(new HashSet<>(Arrays.asList("http", "https")));

  private final ModelLoader urlLoader;

  // Public API.
  @SuppressWarnings("WeakerAccess")
  public HttpUriLoader(ModelLoader urlLoader) {
    this.urlLoader = urlLoader;
  }

  @Override
  public LoadData buildLoadData(@NonNull Uri model, int width, int height,
      @NonNull Options options) {
    return urlLoader.buildLoadData(new GlideUrl(model.toString()), width, height, options);
  }

  @Override
  public boolean handles(@NonNull Uri model) {
    return SCHEMES.contains(model.getScheme());
  }

  /**
   * Factory for loading {@link InputStream}s from http/https {@link Uri}s.
   */
  public static class Factory implements ModelLoaderFactory {

    @Override
    public ModelLoader build(MultiModelLoaderFactory multiFactory) {
      return new HttpUriLoader(multiFactory.build(GlideUrl.class, InputStream.class));
    }
  }
}
public class UrlUriLoader implements ModelLoader {
  private static final Set SCHEMES = Collections.unmodifiableSet(
      new HashSet<>(
          Arrays.asList(
              "http",
              "https"
          )
      )
  );
  private final ModelLoader urlLoader;

  // Public API.
  @SuppressWarnings("WeakerAccess")
  public UrlUriLoader(ModelLoader urlLoader) {
    this.urlLoader = urlLoader;
  }

  @Override
  public LoadData buildLoadData(@NonNull Uri uri, int width, int height,
      @NonNull Options options) {
    GlideUrl glideUrl = new GlideUrl(uri.toString());
    return urlLoader.buildLoadData(glideUrl, width, height, options);
  }

  @Override
  public boolean handles(@NonNull Uri uri) {
    return SCHEMES.contains(uri.getScheme());
  }

  /**
   * Loads {@link java.io.InputStream InputStreams} from {@link android.net.Uri Uris} with http
   * or https schemes.
   */
  public static class StreamFactory implements ModelLoaderFactory {

    @Override
    public ModelLoader build(MultiModelLoaderFactory multiFactory) {
      return new UrlUriLoader<>(multiFactory.build(GlideUrl.class, InputStream.class));
    }
  }
}

根据它们的Factory可以知道构造它们的实例都要执行build(),现在开始梦中梦中梦,然后又要去跟踪这个

multiFactory.build(),2个参数的,这次我就不贴代码了,跟之前分析的是同理,HttpUriLoader、UrlUriLoader

是一样的,经过查找只发现一个

.append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory()),

最后会返回HttpGlideUrlLoader的实例赋值给HttpUriLoader、UrlUriLoader成员变量,

16行和22行,它们分别调用urlLoader.buildLoadData(),这里urlLoader也就是HttpGlideUrlLoader实例,

现在跟踪HttpGlideUrlLoader

@SuppressWarnings("WeakerAccess")
public class HttpGlideUrlLoader implements ModelLoader {
  /**
   * An integer option that is used to determine the maximum connect and read timeout durations (in
   * milliseconds) for network connections.
   *
   * 

Defaults to 2500ms. */ public static final Option TIMEOUT = Option.memory( "com.bumptech.glide.load.model.stream.HttpGlideUrlLoader.Timeout", 2500); @Override public LoadData 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)); } }

26行,哈哈,看到了吧,HttpUrlFetcher,山重水复疑无路 柳暗花明又一村,也看到了请求网络延迟时间2500ms了吧,

这是会构造带有HttpUrlFetcher的实例的LoadData返回,再一级一级返回,返回到MultiModelLoader

class MultiModelLoader implements ModelLoader {
  @Override
  public LoadData buildLoadData(@NonNull Model model, int width, int height,
      @NonNull Options options) {
    Key sourceKey = null;
    int size = modelLoaders.size();
    List> fetchers = new ArrayList<>(size);
    for (int i = 0; i < size; i++) {
      ModelLoader modelLoader = modelLoaders.get(i);
      if (modelLoader.handles(model)) {
        LoadData loadData = modelLoader.buildLoadData(model, width, height, options);
        if (loadData != null) {
          sourceKey = loadData.sourceKey;
          fetchers.add(loadData.fetcher);
        }
      }
    }
    return !fetchers.isEmpty()
        ? new LoadData<>(sourceKey, new MultiFetcher<>(fetchers, exceptionListPool)) : null;
  }
}

12-15行,刚才构造的LoadData实例返回,把内部持有的HttpUrlFetcher实例添加到集合中

18-19行,由于fetchers不为空,所以构造一个LoadData实例,内部持有MultiFetcher实例,MultiFetcher实例内部

又持有fetchers,返回LoadData实例

此时还记得这个LoadData实例返回到哪了吗,是不是晕了哦

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

刚才我们是从这里出发的,然后返回LoadData的集合,再返回上一级,SourceGenerator

哈哈,我们终于回来了,最开始要分析fetcher就是从这个类出发的,分析了这么多就是为了知道loadData.fetcher是

哪个DataFetcher的实现类的实例

class SourceGenerator implements DataFetcherGenerator,
    DataFetcher.DataCallback,
    DataFetcherGenerator.FetcherReadyCallback {
  @Override
  public boolean startNext() {
    ...
    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;
  }
} 
  

16行,既然知道了fetcher是HttpUrlFetcher实例,那么现在跟踪进入,胜利就在眼前了,注意,记住这个this,

这里有时一个回调,待会加载好了回调用

public class MultiModelLoaderFactory {
  ...
  @Override
  public void loadData(Priority priority, DataCallback callback) {
    long startTime = LogTime.getLogTime();
    final InputStream result;
    try {
      result = loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/,
          glideUrl.getHeaders());
    } catch (IOException e) {
      if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "Failed to load data for url", e);
      }
      callback.onLoadFailed(e);
      return;
    }

    if (Log.isLoggable(TAG, Log.VERBOSE)) {
      Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime)
          + " ms and loaded " + result);
    }
    callback.onDataReady(result);
  }

  private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,
      Map headers) throws IOException {
    if (redirects >= MAXIMUM_REDIRECTS) {
      throw new HttpException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
    } else {
      // Comparing the URLs using .equals performs additional network I/O and is generally broken.
      // See http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html.
      try {
        if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
          throw new HttpException("In re-direct loop");

        }
      } catch (URISyntaxException e) {
        // Do nothing, this is best effort.
      }
    }

    // 开始请求URL
    urlConnection = connectionFactory.build(url);
    for (Map.Entry headerEntry : headers.entrySet()) {
      urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
    }
    urlConnection.setConnectTimeout(timeout);
    urlConnection.setReadTimeout(timeout);
    urlConnection.setUseCaches(false);
    urlConnection.setDoInput(true);

    // Stop the urlConnection instance of HttpUrlConnection from following redirects so that
    // redirects will be handled by recursive calls to this method, loadDataWithRedirects.
    urlConnection.setInstanceFollowRedirects(false);

    // Connect explicitly to avoid errors in decoders if connection fails.
    urlConnection.connect();
    // Set the stream so that it's closed in cleanup to avoid resource leaks. See #2352.
    stream = urlConnection.getInputStream();
    if (isCancelled) {
      return null;
    }
    final int statusCode = urlConnection.getResponseCode();
    if (statusCode / 100 == 2) {
      return getStreamForSuccessfulRequest(urlConnection);
    } else if (statusCode / 100 == 3) {
      String redirectUrlString = urlConnection.getHeaderField("Location");
      if (TextUtils.isEmpty(redirectUrlString)) {
        throw new HttpException("Received empty or null redirect url");
      }
      URL redirectUrl = new URL(url, redirectUrlString);
      // Closing the stream specifically is required to avoid leaking ResponseBodys in addition
      // to disconnecting the url connection below. See #2352.
      cleanup();
      return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
    } else if (statusCode == -1) {
      throw new HttpException(statusCode);
    } else {
      throw new HttpException(urlConnection.getResponseMessage(), statusCode);
    }
  }

  private InputStream getStreamForSuccessfulRequest(HttpURLConnection urlConnection)
      throws IOException {
    if (TextUtils.isEmpty(urlConnection.getContentEncoding())) {
      int contentLength = urlConnection.getContentLength();
      stream = ContentLengthInputStream.obtain(urlConnection.getInputStream(), contentLength);
    } else {
      if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "Got non empty content encoding: " + urlConnection.getContentEncoding());
      }
      stream = urlConnection.getInputStream();
    }
    return stream;
  }
  ...
}

这里看起来很熟悉了吧,UrlConnection获取数据流,这里就不详细分析了,一看就懂

22行,加载好的数据流回调到SourceGenerator.

class SourceGenerator implements DataFetcherGenerator,
    DataFetcher.DataCallback,
    DataFetcherGenerator.FetcherReadyCallback {
  ...
  @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);
    }
  }
  ...
} 
  

从这一次回调开始,后面就是一级一级的回调,把图片数据传到控件显示那里,这里data不为null,磁盘缓存策略

默认的,所以会执行9-12行,再返回上一级回调,DecodeJob

class DecodeJob implements DataFetcherGenerator.FetcherReadyCallback,
    Runnable,
    Comparable>,
    Poolable {
  ...
  @Override
  public void reschedule() {
    runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
    callback.reschedule(this);
  }
  ...
}
再回调,EngineJob
class EngineJob implements DecodeJob.Callback,
    Poolable {
  ...
  @Override
  public void reschedule(DecodeJob job) {
    // Even if the job is cancelled here, it still needs to be scheduled so that it can clean itself
    // up.
    getActiveSourceExecutor().execute(job);
  }
  ...
  private GlideExecutor getActiveSourceExecutor() {
    return useUnlimitedSourceGeneratorPool
        ? sourceUnlimitedExecutor : (useAnimationPool ? animationExecutor : sourceExecutor);
  }
  ...
}

这里可以知道GlideExecutor又去执行了job,这次执行的目的不是继续去加载图片,而是清除job,然后run(),

最后会执行到

class DecodeJob implements DataFetcherGenerator.FetcherReadyCallback,
    Runnable,
    Comparable>,
    Poolable {
  ...
  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 void decodeFromRetrievedData() {
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
      logWithTimeAndKey("Retrieved data", startFetchTime,
          "data: " + currentData
          + ", cache key: " + currentSourceKey
          + ", fetcher: " + currentFetcher);
    }
    Resource resource = null;
    try {
      // 获得Resource对象
      resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    } catch (GlideException e) {
      e.setLoggingDetails(currentAttemptingKey, currentDataSource);
      throwables.add(e);
    }
    if (resource != null) {
      // 通知编码并释放资源
      notifyEncodeAndRelease(resource, currentDataSource);
    } else {
      runGenerators();
    }
  }

  ...
}

执行第17行,然后调用decodeFromRetrievedData()

34行,解析刚才加载回来的数据,返回一个Resource实例,currentFetcher就是刚才分析很多得到的

HttpUrlFetcher实例,currentData就是那个赋值给成员变量的图片数据流实例,currentDataSource

表示数据的来源,这里是网络远程DataSource.REMOTE,怎么解析数据的下回分解,继续走主流程哈

41行,跟踪进入

class DecodeJob implements DataFetcherGenerator.FetcherReadyCallback,
    Runnable,
    Comparable>,
    Poolable {
  ...
  private void notifyEncodeAndRelease(Resource resource, DataSource dataSource) {
    if (resource instanceof Initializable) {
      ((Initializable) resource).initialize();
    }

    Resource result = resource;
    LockedResource 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();
      }
      onEncodeComplete();
    }
  }

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

18行和35行,主流程,这里又开始回把数据回调了,此时回调到EngineJob

class EngineJob implements DecodeJob.Callback,
    Poolable {
  ...
  @Override
  public void onResourceReady(Resource resource, DataSource dataSource) {
    // 获取到的图片资源回调
    this.resource = resource;
    this.dataSource = dataSource;
    MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
  }
  ...
  private static class MainThreadCallback implements Handler.Callback {

    @Synthetic
    @SuppressWarnings("WeakerAccess")
    MainThreadCallback() { }

    @Override
    public boolean handleMessage(Message message) {
      EngineJob job = (EngineJob) message.obj;
      switch (message.what) {
        case MSG_COMPLETE:
          job.handleResultOnMainThread();
          break;
        case MSG_EXCEPTION:
          job.handleExceptionOnMainThread();
          break;
        case MSG_CANCELLED:
          job.handleCancelledOnMainThread();
          break;
        default:
          throw new IllegalStateException("Unrecognized message: " + message.what);
      }
      return true;
    }
  }
  ...
}

这消息传递到handleMessage中,23行,跟踪进入

class EngineJob implements DecodeJob.Callback,
    Poolable {
  ...
  private final List cbs = new ArrayList<>(2);

  @Synthetic
  void handleResultOnMainThread() {
    stateVerifier.throwIfRecycled();
    if (isCancelled) {
      resource.recycle();
      release(false /*isRemovedFromQueue*/);
      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);
    hasResource = true;

    // Hold on to resource for duration of request so we don't recycle it in the middle of
    // notifying if it synchronously released by one of the callbacks.
    engineResource.acquire();
    listener.onEngineJobComplete(this, key, engineResource);

    int size = cbs.size();
    for (int i = 0; i < size; i++) {
      ResourceCallback cb = cbs.get(i);
      if (!isInIgnoredCallbacks(cb)) {
        engineResource.acquire();
        cb.onResourceReady(engineResource, dataSource);
      }
    }
    // Our request is complete, so we can release the resource.
    engineResource.release();

    release(false /*isRemovedFromQueue*/);
  }
  ...
}

24-31行,又是回调,哈哈,晕了吗?没关系,马上就到出口了,胜利的曙光就在前方,

这里我们要知道cb是谁的实例,可以知道cbs是一个ResourceCallback的集合,可以搜索,

Glide中ResourceCallback只有SingleRequest一个实现类,那么其实里面装的就是SingleRequest的实例,

哈哈,当然我们还是要找出在哪添加进cbs的

public class Engine implements EngineJobListener,
    MemoryCache.ResourceRemovedListener,
    EngineResource.ResourceListener {
  ...
  public  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) {
    ...
    EngineJob engineJob =
        engineJobFactory.build(
            key,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache);

    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);
    engineJob.start(decodeJob);

    if (Log.isLoggable(TAG, Log.VERBOSE)) {
      logWithTimeAndKey("Started new load", startTime, key);
    }
    return new LoadStatus(cb, engineJob);
  }
  ...
}

这里还记得吗?Engine,整个图片加载的入口

55行,看到了吗?这里往回走,cb知道是哪个的实例了吧,哈哈,SingleRequest的实例,接着跟踪这行

class EngineJob implements DecodeJob.Callback,
    Poolable {
  ...
  void addCallback(ResourceCallback cb) {
    Util.assertMainThread();
    stateVerifier.throwIfRecycled();
    if (hasResource) {
      cb.onResourceReady(engineResource, dataSource);
    } else if (hasLoadFailed) {
      cb.onLoadFailed(exception);
    } else {
      cbs.add(cb);
    }
  }
  ...
}
看明白了吗,把SingleRequest实例传入,然后被cbs添加到集合里面,这下明白了吧,回到EngineJob
class EngineJob implements DecodeJob.Callback,
    Poolable {
  ...
  @Synthetic
  void handleResultOnMainThread() {
    ...
    int size = cbs.size();
    for (int i = 0; i < size; i++) {
      ResourceCallback cb = cbs.get(i);
      if (!isInIgnoredCallbacks(cb)) {
        engineResource.acquire();
        cb.onResourceReady(engineResource, dataSource);
      }
    }
   ...
  }
  ...
}

既然明白了,又接着回调了,到SingleRequest

public final class SingleRequest implements Request,
    SizeReadyCallback,
    ResourceCallback,
    FactoryPools.Poolable {
  ...
  /**
   * A callback method that should never be invoked directly.
   */
  @SuppressWarnings("unchecked")
  @Override
  public void onResourceReady(Resource resource, DataSource dataSource) {
    stateVerifier.throwIfRecycled();
    loadStatus = null;
    if (resource == null) {
      GlideException exception = new GlideException("Expected to receive a Resource with an "
          + "object of " + transcodeClass + " inside, but instead got null.");
      onLoadFailed(exception);
      return;
    }

    Object received = resource.get();
    if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
      releaseResource(resource);
      GlideException exception = new GlideException("Expected to receive an object of "
          + transcodeClass + " but instead" + " got "
          + (received != null ? received.getClass() : "") + "{" + received + "} inside" + " "
          + "Resource{" + resource + "}."
          + (received != null ? "" : " " + "To indicate failure return a null Resource "
          + "object, rather than a Resource object containing null data."));
      onLoadFailed(exception);
      return;
    }

    if (!canSetResource()) {
      releaseResource(resource);
      // We can't put the status to complete before asking canSetResource().
      status = Status.COMPLETE;
      return;
    }

    onResourceReady((Resource) resource, (R) received, dataSource);
  }

  /**
   * 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 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 {
      if ((requestListener == null
          || !requestListener.onResourceReady(result, model, target, dataSource, isFirstResource))
          && (targetListener == null
          || !targetListener.onResourceReady(result, model, target, dataSource, isFirstResource))) {
        Transition animation =
            animationFactory.build(dataSource, isFirstResource);
        // 最终资源会加载回这里,找到target对应的类
        target.onResourceReady(result, animation);
      }
    } finally {
      isCallingCallbacks = false;
    }

    notifyLoadSuccess();
  }
  ...
}

执行41行后,看72行,大家睡觉的醒醒,要到站了

target还记得吧,前面反复提醒,target这篇文章是DrawableImageViewTarget实例,去看onResourceReady(),

发现并没有这个回调方法,那么肯定在父类或者爷爷类或者爷爷的爸爸等里面,果然ImageViewTarget里面的

public abstract class ImageViewTarget extends ViewTarget
    implements Transition.ViewAdapter {
  ...
  @Override
  public void onResourceReady(Z resource, @Nullable Transition transition) {
    if (transition == null || !transition.transition(resource, this)) {
      setResourceInternal(resource);
    } else {
      maybeUpdateAnimatable(resource);
    }
  }
  ...
  private void setResourceInternal(@Nullable Z resource) {
    // Order matters here. Set the resource first to make sure that the Drawable has a valid and
    // non-null Callback before starting it.
    setResource(resource);
    maybeUpdateAnimatable(resource);
  }

  protected abstract void setResource(@Nullable Z resource);
  ...
}

由于没有设置动画,所以执行第7行,接着执行第16行,不过可以看到setResource是一个抽象方法,那么

具体实现就是在子类中,回到DrawableImageViewTarget

public class DrawableImageViewTarget extends ImageViewTarget {
  ...
  @Override
  protected void setResource(@Nullable Drawable resource) {
    // 最后显示加载到的图片
    view.setImageDrawable(resource);
  }
  ...
}

开始显示图片,哈哈,童鞋们,这回真的到站了哦

又可以愉快玩耍了


下一篇 Android 图片加载框架Glide缓存原理源码分析



你可能感兴趣的:(Android)