Glide 4.9源码解析-图片加载流程

本文Glide源码基于4.9,版本下载地址以下:Glide 4.9java

前言

因为Glide源码真的很复杂,所以本文只分析和贴出与图片加载流程相关的功能以及代码。另外本文Glide源码基于4.9,与3.x的源码仍是存在差别的,可是总体流程变化不大。git

对于Glide这个强大的Android图片加载开源框架,相信你们并不陌生吧,反正笔者的话,正常项目中用的图片加载框架大多数都是它,由于用起来真的很方便快捷,用起来便捷,但真的说明它的源码就是那么简单吗?因此今天想揭开Glide的神秘面纱,从源码来分析一下Glide的图片加载流程。github

在多数状况下,咱们想要在界面加载并展现一张图片只须要一行代码就能实现了,以下所示:缓存

Glide.with(this).load(url).into(imageView);
复制代码

因此咱们对Glide图片加载流程的源码分析能够分为三部曲:网络

  • with
  • load
  • into

接下来就让咱们一块儿来弹奏这三部曲!多线程

1、with

1. 做用

  1. 获得RequestManager对象
  2. 预先建立好对图片进行一系列操做(加载,编解码,转码)的对象,并添加到Glide的注册表registry中
  3. 将Glide加载图片的生命周期与Appliction/Activity/Fragment进行绑定

2. 流程

2.1 时序图

首先,从使用中咱们知道,第一部曲中咱们先调用的是Glide的with方法,因此先来看看这个方法app

Glide#with框架

/** * Application类型 */
  public static RequestManager with(@NonNull Context context) {
  	//getRetriever会返回RequestManagerRetriever的单例对象
  	//RequestManagerRetriever的get会返回RequestManager对象并绑定图片加载的生命周期
    return getRetriever(context).get(context);
  }

  /** * 非Application类型 */
  public static RequestManager with(@NonNull Activity activity) {
  	//跟Application类型同样会调用RequestManagerRetriever的get获取RequestManager对象
  	//不过需注意在这里传递的参数为Activity
    return getRetriever(activity).get(activity);
  }

  public static RequestManager with(@NonNull FragmentActivity activity) {
    return getRetriever(activity).get(activity);
  }
  ...
复制代码

能够发现,with方法是Glide类中的一组静态方法,在Glide中有不少的重载方法,能够传入Context,Activity,Fragment等,而后with里面的实现很简单,就一句代码,看返回类型就知道其功能是干吗,就是返回一个RequestManager对象。那么具体是如何来获得这个对象呢,让咱们来看看!异步

2.2 获取RequestManagerRetriever对象

在返回RequestManager对象对象前首先会返回RequestManagerRetriever对象,无论with的参数是什么,调用的都是getRetriever方法,并且getRetriever并无重载方法,因此获取RequestManagerRetriever对象的步骤是同样的,让咱们来追踪一下究竟是如何获取到这个RequestManagerRetriever对象的。ide

private static RequestManagerRetriever getRetriever(@Nullable Context context) {
     ...
	//1.调用Glide.get获取到Glide的对象,Glide对象中封装了RequestManagerRetriever对象
	//2.经过Glide的getRequestManagerRetriever()获取到RequestManagerRetriever对象
    return Glide.get(context).getRequestManagerRetriever();
  }
 
  public static Glide get(@NonNull Context context) {
    if (glide == null) {
      synchronized (Glide.class) {
        if (glide == null) {
          //重点关注 
          checkAndInitializeGlide(context);
        }
      }
    }
    return glide;
  }


  private static void checkAndInitializeGlide(@NonNull Context context) {
    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(@NonNull Context context, @NonNull GlideBuilder builder) {
      ....
      	//构造Glide的实体对象,此时的builder为GlideBuilder
        Glide glide = builder.build(applicationContext);   
      ....
  }
复制代码

首先getRetriever方法看起来好像跟with里面的代码很相似,其实主要作了两件事:

  • 经过Glide.get获取到Glide的对象
  • 调用Glide的getRequestManagerRetriever()获取到RequestManagerRetriever对象

在Glide的get方法就是简单标准的单例实现。在initializeGlide中会经过GlideBuilder的build来构造Glide的实体对象,这个Glide的构造很重要,所以咱们来看看GlideBuilder的build方法是如何来构建Glide对象的

@NonNull
  Glide build(@NonNull Context context) {
    ......  
	//构建管理线程池与缓存的执行引擎
    if (engine == null) {
      engine =
          new Engine(
              memoryCache,
              diskCacheFactory,
              diskCacheExecutor,
              sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor(),
              GlideExecutor.newAnimationExecutor(),
              isActiveResourceRetentionAllowed);
    }

	//构建了一个RequestManagerRetriever对象
    RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory);

	//构建Glide对象,并将上面的众多线程池和RequestManagerRetriever对象封装进去
    return new Glide(
        context,
        engine,
        memoryCache,
        bitmapPool,
        arrayPool,
        requestManagerRetriever,
        connectivityMonitorFactory,
        logLevel,
        defaultRequestOptions.lock(),
        defaultTransitionOptions,
        defaultRequestListeners,
        isLoggingRequestOriginsEnabled);
  }
}

public class Glide implements ComponentCallbacks2 {
      Glide(
      @NonNull Context context,
      @NonNull Engine engine,
      @NonNull MemoryCache memoryCache,
      @NonNull BitmapPool bitmapPool,
      @NonNull ArrayPool arrayPool,
      @NonNull RequestManagerRetriever requestManagerRetriever,
      @NonNull ConnectivityMonitorFactory connectivityMonitorFactory,
      int logLevel,
      @NonNull RequestOptions defaultRequestOptions,
      @NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions,
      @NonNull List<RequestListener<Object>> defaultRequestListeners,
      boolean isLoggingRequestOriginsEnabled) {
          ...
          //将RequestManagerRetriever对象赋值到成员变量中
          this.requestManagerRetriever = requestManagerRetriever;
          ....
          //解码器
          StreamBitmapDecoder streamBitmapDecoder = new StreamBitmapDecoder(downsampler, arrayPool);    
          //添加到注册表中 
          registry
              .append(Registry.BUCKET_BITMAP, InputStream.class, Bitmap.class, streamBitmapDecoder)
              ....
              /* Models */
              //重点关注InputStreamRewinder
              .register(new InputStreamRewinder.Factory(arrayPool))
              ....
              //重点关注StringLoader.StreamFactory()
              .append(String.class, InputStream.class, new StringLoader.StreamFactory())
              .... 
              //重点关注HttpUriLoader.Factory()
        	 .append(Uri.class, InputStream.class, new HttpUriLoader.Factory())
              ....
              //重点关注HttpGlideUrlLoader
              .append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())
              ....
              /* Transcoders */
	    	 //重点关注BitmapDrawableTranscoder
        	 .register(
            	 Bitmap.class,
            	 BitmapDrawable.class,
            	 new BitmapDrawableTranscoder(resources))
              .....
          
      }
}

复制代码

从上面能够看出Glide对象的建立干的事情贼多,也极其复杂,总的来讲其职责以下:

  • 建立RequestManagerRetriever对象
  • 建立管理线程池与缓存的执行引擎Engine对象(下文需用到)
  • 构建registry,注册了众多编解码器(下文需用到)

其中在注册表registry中,上面的代码只列举了几个下面会用到的编解码器,实际上注册表的东西远不止这几个。咱们从新确认下咱们的目标获取RequestManagerRetriever对象,在上面的代码中已经new出了一个RequestManagerRetriever对象,并赋值到了Glide的成员变量,接下来就能够经过Glide的getRequestManagerRetriever方法获取到这个RequestManagerRetriever对象了。

2.3 获取RequestManager对象

让咱们从新看看其中一个with方法

RequestManagerRetriever#with

public static RequestManager with(@NonNull Context context) {
    return getRetriever(context).get(context);
  }
复制代码

当咱们获取到了RequestManagerRetriever对象后,就须要经过RequestManagerRetriever的get方法获取RequestManager对象,在RequestManagerRetriever类中get跟Glide的with同样也有不少重载方法,重载方法对不一样参数的处理是不一样的,根据不一样的处理能够分为两种类型的参数:

  • Application类型
  • 非Application类型(Activity/Fragment)

2.3.1 获取到Application类型的RequestManager对象

RequestManagerRetriever#get

//Application类型
  public RequestManager get(@NonNull Context context) {
    if (context == null) {
      throw new IllegalArgumentException("You cannot start a load on a null Context");
    } else if (Util.isOnMainThread() && !(context instanceof Application)) {
      //若在主线程且context不为Application类型
      if (context instanceof FragmentActivity) {
        return get((FragmentActivity) context);
      } else if (context instanceof Activity) {
        return get((Activity) context);
      } else if (context instanceof ContextWrapper) {
        return get(((ContextWrapper) context).getBaseContext());
      }
    }
	//若不在主线程或者为Application类型的调用getApplicationManager获取一个RequestManager对象
    return getApplicationManager(context);
  }
复制代码

能够发现,参数为context的get有两种处理:

  1. 若是在主线程且context不为Application类型的就直接调用非Application类型的get方法
  2. 若是不在主线程或者为Application类型的就调用getApplicationManager获取RequestManager对象

在这里咱们分析的是Application类型的,因此直接看getApplicationManager方法

RequestManagerRetriever#getApplicationManager

private RequestManager getApplicationManager(@NonNull Context context) {
    if (applicationManager == null) {
      synchronized (this) {
        if (applicationManager == null) {
          //get方法为获取Glide的单例对象,
          //因为上面已经建立好Glide的单例对象了,因此在这里就直接取Glide的单例对象不需建立
          Glide glide = Glide.get(context.getApplicationContext());
          applicationManager =
              factory.build(
                  glide,
                  new ApplicationLifecycle(),
                  new EmptyRequestManagerTreeNode(),
                  context.getApplicationContext());
        }
      }
    }
    return applicationManager;
  }

  public interface RequestManagerFactory {
    @NonNull
    RequestManager build( @NonNull Glide glide, @NonNull Lifecycle lifecycle, @NonNull RequestManagerTreeNode requestManagerTreeNode, @NonNull Context context);
  }

  private static final RequestManagerFactory DEFAULT_FACTORY = new RequestManagerFactory() {
    @NonNull
    @Override
    public RequestManager build(@NonNull Glide glide, @NonNull Lifecycle lifecycle, @NonNull RequestManagerTreeNode requestManagerTreeNode, @NonNull Context context) {
      return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
    }
  };
}
复制代码

在上面的方法中,也是标准的单例实现,经过上面的分析咱们知道Glide已经建立好了,而且Glide的get也是单例实现,因此直接获取到Glide对象,并new了一个ApplicationLifecycle,而后传入Glide和ApplicationLifecycle对象等并建立了RequestManager对象从而实现与Application生命周期的绑定。

那么为何Glide能够直接绑定Application的生命周期呢?

这是由于Application对象的生命周期就是App的生命周期,因此Glide加载图片的生命周期直接与与应用程序的生命周期绑定的就行,不须要作特殊处理。

2.3.2 获取到非Application类型的RequestManager对象

这里咱们只以参数为Activity类型的为表明,由于其它非Application类型的处理与Activity基本是相似的。

RequestManagerRetriever#get

/** * 非Application类型 */
  public RequestManager get(@NonNull FragmentActivity activity) {
    if (Util.isOnBackgroundThread()) {
	  //若是在子线程则直接调用Aplication类型的get
      return get(activity.getApplicationContext());
    } else {
	  //判断Activity是否销毁
      assertNotDestroyed(activity);
	  //获取FragmentManager对象
      FragmentManager fm = activity.getSupportFragmentManager();
	  //经过调用supportFragmentGet返回RequestManager
      return supportFragmentGet(
          activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }
复制代码

对于非Application类型的,首先要判断这个请求是在主线程中仍是子线程中,若是是子线程中就调用Application类型的get方法,这也能够明白,由于在子线程中Glide的生命周期应该与Application的生命周期相一致。

若是是在主线程中,就调用supportFragmentGet方法来跟Activity的生命周期绑定。

RequestManagerRetriever#supportFragmentGet

private RequestManager supportFragmentGet( @NonNull Context context, @NonNull FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
    //获取SupportRequestManagerFragment
    SupportRequestManagerFragment current =
        getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
    //实现建立,添加Fragment 
    RequestManager requestManager = current.getRequestManager();
	//若是首次加载则初始化requestManager
    if (requestManager == null) { 
      Glide glide = Glide.get(context);
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
	  //设置到SupportRequestManagerFragment中
	  current.setRequestManager(requestManager);
    }
    return requestManager;
  }
复制代码

supportFragmentGet是如何与Activity进行绑定的呢?其流程以下:

  1. 建立隐藏的Fragment
  2. 向当前的Activity添加一个隐藏的Fragment
  3. 建立RequestManager对象,而后将RequestManager与隐藏的Fragment的生命周期进行绑定

也许你会问为何绑定了Activity中隐藏的Fragment生命周期就能与Activity进行绑定了呢?这是由于Fragment的生命周期与Activity是同步的,因此经过绑定的隐藏的Fragment就能监听Activity的生命周期,进而实现Glide加载图片的生命周期与Activity同步,而且经过这样的方法还能避免Glide持有Activity的实例而发生内存泄漏问题。

3. 小结

到这里with的工做就结束了,让咱们来总结一下with的主要工做

  • 构建Glide对象
    • 建立管理线程池与缓存的执行引擎Engine对象
    • 构建registry,注册了众多编解码器
    • 构建RequestManagerRetriever对象
  • 构建RequestManager对象
    • 若是在子线程中加载图片或with中的参数为Application类型,则Glide图片加载的生命周期与Application生命周期绑定
    • 不然,Glide图片加载的生命周期与Activity或Fragment的生命周期绑定,绑定的方式:向当前的Activity/Fragment添加一个隐藏的Fragment,而后绑定这个隐藏的Fragment的生命周期。

2、load

1. 做用

建立一个目标为Drawable的图片加载请求,传入须要加载的资源(String,URL,URI等)

2. 流程

2.1 时序图

2.2 建立RequestBuilder对象

从上面对with的分析,咱们知道with最终会返回一个RequestManager对象,故第二部曲的开始就是RequestManager的load方法。

RequestManager#load

public RequestBuilder<Drawable> load(@Nullable String string) {
  	//1.asDrawable建立一个目标为Drawable的图片加载请求
  	//2.调用load将加载的资源传入
    return asDrawable().load(string);
  }

  public RequestBuilder<Drawable> load(@Nullable Uri uri) {
    return asDrawable().load(uri);
  }

  public RequestBuilder<Drawable> load(@Nullable URL url) {
    return asDrawable().load(url);
  }
.....
复制代码

能够发现load在RequestManager也是有不少重载方法的,可是下面咱们只分析最多见的加载图片的load参数,即load(String url)。

在RequestManager的load方法中,首先会先调用asDrawable,让咱们来看看asDrawable

public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
  }

  public <ResourceType> RequestBuilder<ResourceType> as( @NonNull Class<ResourceType> resourceClass) {
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }
复制代码

上面的代码很简单,就是建立了一个目标为Drawable的图片加载请求RequestBuilder。

2.3 传入图片URL地址

因为asDrawable返回的是RequestBuilder对象,所以下一步将会调用RequesBuilder的load方法

RequesBuilder#load

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

  private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
  	//将数据赋值给RequestBuilder的静态成员变量
    this.model = model;
    isModelSet = true;
    return this;
  }
复制代码

上面的代码很容易理解,load调用了loadGeneric方法,loadGeneric方法中将数据,此时将String类型的model赋值给了RequestBuilder的静态成员变量。

3. 小结

load估计是三部曲中最简单的一部曲子了,代码简单,也很容易理解。此部曲也是3.x与4.9的区别之一,在3.x的源码中load原本还应该完成一项任务,即预先建立好对图片进行一系列操做(加载,编解码,转码)的对象。而经过上述对with的分析,咱们知道在4.9的源码中,这项工做已经交给with来处理了,因此load相比较其它两个来讲,其工做是比较简单的。

3、into

!!!高能预警,into的源码分析将会很长很长很长

1. 做用

在子线程中网络请求解析图片,并回到主线程中展现图片

2. 流程

下列的源码基于load参数为String,不采起内存缓存,磁盘缓存的状况下

在上面对load的解析中咱们知道,load执行完后返回的是RequestBuilder对象,因此into的入口就是RequestBuilder

RequestBuilder#into

public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    
     .....
	//返回ViewTarget对象
    return into(
    	//glideContext为GlideContext类型
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions,
        //含有绑定主线程Handler的线程池
        Executors.mainThreadExecutor());
}
复制代码

在上面的代码中,咱们知道在调用into以前会先获取要传递的参数,这里咱们重点关注第一个参数和第四个参数。

2.1 建立ViewTarget对象

首先咱们先分析GlideContext的buildImageViewTarget方法.

GlideContext#buildImageViewTarget

public <X> ViewTarget<ImageView, X> buildImageViewTarget( @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
    return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
  }
复制代码

此时传入的transcodeClass其实就是咱们在第二部曲中分析的asDrawable中传入的Drawable.class,而后继续调用了ImageViewTargetFactory的buildTarget方法。

ImageViewTargetFactory#buildTarget

public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view, @NonNull Class<Z> clazz) {
    if (Bitmap.class.equals(clazz)) {
	  //如果调用了asBitmap方法
      return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
    } else if (Drawable.class.isAssignableFrom(clazz)) {
      //不然
      return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
    } else {
      throw new IllegalArgumentException(
          "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
    }
  }
复制代码

由于咱们并无调用asBitmap方法,而且传入的是Drawable类型,因此返回的ViewTarget对象应该是DrawableImageViewTarget,这个对象在展现图片时将会用到。

!!!注:下文代码中出现的target,若是没有特殊说明都是DrawableImageViewTarget对象。

2.2 建立MAIN_THREAD_EXECUTOR

让咱们回到前面的into方法。

public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    ....
	//返回ViewTarget对象
    return into(
    	//buildImageViewTarget建立ViewTarget对象
    	//transcodeClass若调用了asBitmap则为Bitmap,相应的返回BitmapImageViewTarget,
	    //不然transcodeClass为Drawable类型,返回DrawableImageViewTarget 
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions,
        //含有绑定主线程Handler的线程池
        Executors.mainThreadExecutor());
  }
复制代码

接着咱们继续分析第四个参数

Executors#mainThreadExecutor

private static final Executor MAIN_THREAD_EXECUTOR =
      new Executor() {
       //绑定主线程的Looper
        private final Handler handler = new Handler(Looper.getMainLooper());

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

public static Executor mainThreadExecutor() {
    return MAIN_THREAD_EXECUTOR;
  }
复制代码

从上面能够发如今这个mainThreadExecutor中返回的是MAIN_THREAD_EXECUTOR,而MAIN_THREAD_EXECUTOR声明了一个绑定了主线程Looper的Handler,而后这个线程池的execute方法会执行handler的post方法,至关于在主线程中执行command的run方法。(这里先讲明白这个线程池,由于当分析到最后在主线程中显示图片时会从新分析到这个参数,另外这里涉及到了Handler机制的知识,不懂的能够看看前面写的博客Android之Handler机制

分析完了into的两个参数,咱们接下来就看看这个重载into方法

RequestBuilder#into

private <Y extends Target<TranscodeType>> Y into( @NonNull Y target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> options, Executor callbackExecutor) {
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }
    //构建Requset对象,发出加载图片请求
    //注意第四个参数传进去的是含有绑定主线程的Handler的线程池
    Request request = buildRequest(target, targetListener, options, callbackExecutor);
    //在开始前先释放掉target对象已存在的请求
    Request previous = target.getRequest();
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
      request.recycle();
      
      if (!Preconditions.checkNotNull(previous).isRunning()) {
        previous.begin();
      }
      return target;
    }
		
    requestManager.clear(target);

	//将请求设置到target中
    target.setRequest(request);
	//分发并执行网络请求Request,此时的requestManager就是
    requestManager.track(target, request);

    return target;
  }
复制代码

咱们能够发如今这个方法中,其实主要的工做有两个:一是构建网络请求的Request,二是执行网络请求对象Request,接下来咱们就分别对这两个工做进行分析。

2.3 构建网络请求对象Request

RequestBuilder#buildRequest

private Request buildRequest( Target<TranscodeType> target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> requestOptions, Executor callbackExecutor) {
    //重点关注buildRequestRecursive方法 
    return buildRequestRecursive(
        target,
        targetListener,
        /*parentCoordinator=*/ null,
        transitionOptions,
        requestOptions.getPriority(),
        requestOptions.getOverrideWidth(),
        requestOptions.getOverrideHeight(),
        requestOptions,
        callbackExecutor);
  }

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

    .....
    //重点关注buildThumbnailRequestRecursive方法
    Request mainRequest =
        buildThumbnailRequestRecursive(
            target,
            targetListener,
            parentCoordinator,
            transitionOptions,
            priority,
            overrideWidth,
            overrideHeight,
            requestOptions,
            callbackExecutor);

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


  private Request buildThumbnailRequestRecursive( Target<TranscodeType> target, RequestListener<TranscodeType> targetListener, @Nullable RequestCoordinator parentCoordinator, TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority, int overrideWidth, int overrideHeight, BaseRequestOptions<?> requestOptions, Executor callbackExecutor) {
      ....
      //重点关注,关键代码
	  Request fullRequest =
          obtainRequest(
              target,
              targetListener,
              requestOptions,
              coordinator,
              transitionOptions,
              priority,
              overrideWidth,
              overrideHeight,
              callbackExecutor);
      ........ 
  }

  private Request obtainRequest( Target<TranscodeType> target, RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> requestOptions, RequestCoordinator requestCoordinator, TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority, int overrideWidth, int overrideHeight, Executor callbackExecutor) {
    //调用了SingleRequest的obtain方法,将load中调用的全部API参数都组装到Request对象当中
    //此时的callbackExecutor为含有绑定主线程Handler的线程池 
    return SingleRequest.obtain(
        context,
        glideContext,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        glideContext.getEngine(),
        transitionOptions.getTransitionFactory(),
        callbackExecutor);
  }
复制代码

通过一步一步调用,最终将会执行SingleRequest的obtain方法,因此咱们继续看这个方法

SingleRequest#obtain方法

public static <R> SingleRequest<R> obtain( Context context, GlideContext glideContext, Object model, Class<R> transcodeClass, BaseRequestOptions<?> requestOptions, int overrideWidth, int overrideHeight, Priority priority, Target<R> target, RequestListener<R> targetListener, @Nullable List<RequestListener<R>> requestListeners, RequestCoordinator requestCoordinator, Engine engine, TransitionFactory<? super R> animationFactory, Executor callbackExecutor) {
    @SuppressWarnings("unchecked") SingleRequest<R> request =
        (SingleRequest<R>) POOL.acquire();
    if (request == null) {
	  //建立SingleRequest对象
      request = new SingleRequest<>();
    }
	//将传入load中的API参数赋值到SingleRequest的成员变量
	//最后一个参数为主线程的线程池
    request.init(
        context,
        glideContext,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        engine,
        animationFactory,
        callbackExecutor);
    return request;
  }
  //对成员变量赋值
  private synchronized void init( Context context, GlideContext glideContext, Object model, Class<R> transcodeClass, BaseRequestOptions<?> requestOptions, int overrideWidth, int overrideHeight, Priority priority, Target<R> target, RequestListener<R> targetListener, @Nullable List<RequestListener<R>> requestListeners, RequestCoordinator requestCoordinator, Engine engine, TransitionFactory<? super R> animationFactory, Executor callbackExecutor) {
    this.context = context;
    this.glideContext = glideContext;
    this.model = model;
    this.transcodeClass = transcodeClass;
    this.requestOptions = requestOptions;
    this.overrideWidth = overrideWidth;
    this.overrideHeight = overrideHeight;
    this.priority = priority;
    this.target = target;
    this.targetListener = targetListener;
    this.requestListeners = requestListeners;
    this.requestCoordinator = requestCoordinator;
    this.engine = engine;
    this.animationFactory = animationFactory;
    this.callbackExecutor = callbackExecutor;
    status = Status.PENDING;

    if (requestOrigin == null && glideContext.isLoggingRequestOriginsEnabled()) {
      requestOrigin = new RuntimeException("Glide request origin trace");
    }
  }
复制代码

这个obtain方法其实就是建立了SingleRequest对象,而后调用了init方法进行成员变量的赋值,因此构建的网络请求对象就是SingleRequest对象。

2.4 执行网络请求对象Request

让咱们回到into方法

private <Y extends Target<TranscodeType>> Y into( @NonNull Y target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> options, Executor callbackExecutor) {
    //构建Requset对象,发出加载图片请求
    //最终构建的是SingleRequest对象
    Request request = buildRequest(target, targetListener, options, callbackExecutor);  
    .....
	//分发并执行网络请求Request,此时的requestManager就是RequestManager对象
    //target为上述建立的DrawableImageViewTarget(若是忘记能够从新看回2.1)
    //request就是建立完成的singleRequest对象 
    requestManager.track(target, request);

    return target;
  }
复制代码

这时候咱们已经成功构建出了SingleRequest对象了,而后调用了RequestManager的track方法进行分发并执行这个请求

2.4.1 加载前

RequestManager#track

synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
    targetTracker.track(target);
	//执行网络请求
    requestTracker.runRequest(request);
  }
复制代码

RequestTracker#runRequest

public void runRequest(@NonNull Request request) {
    //将每一个提交的请求加入到一个set中,从而实现管理请求
    requests.add(request);
	//判断Glide当前是否处于暂停状态
    if (!isPaused) {
	  //若是不暂停,则调用SingleRequest的begin方法来执行request
      request.begin();
    } else {
      request.clear();
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Paused, delaying request");
      }
	  //若是暂停,则先将当前的请求添加到待执行队列里面,等待暂停状态解除后再执行
      pendingRequests.add(request);
    }
  }
复制代码

在加载图片前,即开启网络请求前咱们须要将每一个请求加到set中来进行管理请求,而且还须要判断Glide当前的状态,由于咱们如今分析的是图片加载流程,显然这里的Glide不是暂停状态,因此会执行request的begin方法,因为在上面咱们已经分析了网络请求对象为SingleRequest,因此这里的request为SingleRequest对象。

2.4.2 加载时

接着咱们来看看SingleRequest的begin方法

SingleRequest#begin

public synchronized void begin() {
    ....
	//model为load传入的图片URL地址
    if (model == null) {
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
        width = overrideWidth;
        height = overrideHeight;
      }
       
      int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
	  //若是传入的URL地址为空,则会调用onLoadFailed
      onLoadFailed(new GlideException("Received null model"), logLevel);
      return;
    }

    status = Status.WAITING_FOR_SIZE;
    if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
	  //重点关注
      onSizeReady(overrideWidth, overrideHeight);
    } else {
    &emsp;//getsize计算宽高,而后执行onSizeReady方法
      target.getSize(this);
    }

    if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
        && canNotifyStatusChanged()) {
      //在图片请求成功前,会先使用Loading占位图代替最终的图片显示 
      target.onLoadStarted(getPlaceholderDrawable());
    }
    .....
  }
复制代码
1. onLoadFailed

从上面的代码中咱们能够发现当model为null时,即load传入的图片地址为空时,会调用onLoadFailed方法

SingleRequest#onLoadFailed

private synchronized void onLoadFailed(GlideException e, int maxLogLevel) {
    .....

    loadStatus = null;
    status = Status.FAILED;

    isCallingCallbacks = true;
    try {
      //TODO: what if this is a thumbnail request?
      boolean anyListenerHandledUpdatingTarget = false;
      if (requestListeners != null) {
        for (RequestListener<R> listener : requestListeners) {
          anyListenerHandledUpdatingTarget |=
              listener.onLoadFailed(e, model, target, isFirstReadyResource());
        }
      }
      anyListenerHandledUpdatingTarget |=
          targetListener != null
              && targetListener.onLoadFailed(e, model, target, isFirstReadyResource());

      if (!anyListenerHandledUpdatingTarget) {
	  	//重点关注这个方法
        setErrorPlaceholder();
      }
    } finally {
      isCallingCallbacks = false;
    }

    notifyLoadFailed();
  }


  private synchronized void setErrorPlaceholder() {
    if (!canNotifyStatusChanged()) {
      return;
    }

    Drawable error = null;
	//先获取fallback的图片
    if (model == null) {
      error = getFallbackDrawable();
    }
    //若没有设置fallback图,则获取error图
    if (error == null) {
      error = getErrorDrawable();
    }
    //若没有error图,则再获取一个loading的占位图
    if (error == null) {
      error = getPlaceholderDrawable();
    }
    //target为DrawableImageViewTarget 
    target.onLoadFailed(error);
  }
复制代码

在onLoadFailed方法中咱们只须要关注setErrorPlaceholder方法,而在setErrorPlaceholder中主要的逻辑就是获取错误时须要展现的图片,按fallback>error>loading的优先级来获取错误时的图片,而后调用DrawableImageViewTarget的onLoadFailed方法。经过查看DrawableImageViewTarget,咱们能够发现这个类中并无onLoadFailed方法,因此咱们天然而然找父类ImageViewTarget是否存在这个方法.

ImageViewTarget#onloadFailed

public void onLoadFailed(@Nullable Drawable errorDrawable) {
    super.onLoadFailed(errorDrawable);
    setResourceInternal(null);
	//调用setDrawable将图片显示出来
    setDrawable(errorDrawable);
  }

  public void setDrawable(Drawable drawable) {
    //view就是ImageView,将图片展现出来
    view.setImageDrawable(drawable);
  }

复制代码

到这里,错误的图片就被显示出来,从这里咱们能够看出Glide显示错误的图片的原则就是:当传入图片的url为null时,会才采用fallback/error/loading的占位图进行代替。

2. onLoadStarted

分析完onLoadFailed,咱们回到SingleRequest的begin方法,原本按代码顺序接下来应该分析的是onSizeReady,可是因为这个方法比较复杂而且onLoadStarted与onLoadStarted很相似,因此咱们先分析onLoadStarted,把onSizeReady放到最后。

SingleRequest#begin 与onLoadStarted相关的代码

if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
        && canNotifyStatusChanged()) {
      //在图片请求成功前,会先使用Loading占位图代替最终的图片显示 
      target.onLoadStarted(getPlaceholderDrawable());
    }
复制代码

看上面这个逻辑就是当图片正在请求时或者等待执行onSizeReady方法时,就执行DrawableImageViewTarget的onLoadStarted方法,从onLoadFailed方法的分析咱们已经知道,onLoadFailed方法是在DrawableImageViewTarget父类ImageViewTarget中,故onLoadStarted也是在ImageViewTarget中,至于参数就是loading的占位图。

ImageViewTarget#onLoadStarted

public void onLoadStarted(@Nullable Drawable placeholder) {
    super.onLoadStarted(placeholder);
    setResourceInternal(null);
	//在图片请求开始前,会先使用Loading占位图代替最终的图片显示
    setDrawable(placeholder);
  }

  public void setDrawable(Drawable drawable) {
    //将图片展现出来
    view.setImageDrawable(drawable);
  }
复制代码

而后将loading的占位图显示出来,即图片请求成功前,会使用Loading占位图代替最终的图片显示。这也算是咱们常用的一个功能了。

3. onSizeReady

到这里咱们终于要分析重头戏onSizeReady了,咱们先贴出相关代码

SingleRequest#begin 与onSizeReady相关的代码

//图片加载有两种状况:
	//1.使用了override()的API为图片指定了固定宽高
	//2.无使用
    if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
		//第一种状况,指定了宽高的话调用onSizeReady加载
      onSizeReady(overrideWidth, overrideHeight);
    } else {
    &emsp;//getsize计算宽高,而后执行onSizeReady方法
      //(从DrawableImageViewTarget中向上追踪,会在ViewTarget中发现这个方法)
      target.getSize(this);
    }
复制代码

这个咱们只分析onSizeReady,由于getSize方法最终也是会调用onSizeReady的。

SingleRequest#onSizeReady

@Override
  public synchronized void onSizeReady(int width, int height) {
    ....
    status = Status.RUNNING;

    loadStatus =
    	//重点关注,调用Engine的load构建任务
    	//重点关注倒数第二个参数,传入自身SingleRequest,在回调的时候会使用
    	//重点关注倒数第一个参数,传入有绑定主线程的Handler的线程池callbackExectuter
        engine.load(
            glideContext,
            model,
            requestOptions.getSignature(),
            this.width,
            this.height,
            requestOptions.getResourceClass(),
            transcodeClass,
            priority,
            requestOptions.getDiskCacheStrategy(),
            requestOptions.getTransformations(),
            requestOptions.isTransformationRequired(),
            requestOptions.isScaleOnlyOrNoTransform(),
            requestOptions.getOptions(),
            requestOptions.isMemoryCacheable(),
            requestOptions.getUseUnlimitedSourceGeneratorsPool(),
            requestOptions.getUseAnimationPool(),
            requestOptions.getOnlyRetrieveFromCache(),
            this,
            callbackExecutor);
  }
复制代码

能够看出onSizeReady的实现交给了Engine的load方法实现了,这个Engine对象就是在第一部曲with中Glide构建时提到的执行引擎,在这里还须要特别注意的是传给load的最后两个参数,由于这两个参数在后面的分析须要用到。

构建任务

Engine#load

public synchronized <R> LoadStatus load( GlideContext glideContext, Object model, Key signature, int width, int height, Class<?> resourceClass, Class<R> transcodeClass, Priority priority, DiskCacheStrategy diskCacheStrategy, Map<Class<?>, Transformation<?>> transformations, boolean isTransformationRequired, boolean isScaleOnlyOrNoTransform, Options options, boolean isMemoryCacheable, boolean useUnlimitedSourceExecutorPool, boolean useAnimationPool, boolean onlyRetrieveFromCache, ResourceCallback cb, Executor callbackExecutor) {
    
    .....
	//从缓存中查找key对应的任务
    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
	  //若是走到这说明该任务已经正在执行了,无需再次构建执行
	  //能够先不看,从后面分析完后从新回头看这个
      current.addCallback(cb, callbackExecutor);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Added to existing load", startTime, key);
      }
      return new LoadStatus(cb, current);
    }
	//走到这,说明这是个新任务
    //建立EngineJob对象,用来开启线程(异步加载图片)
    EngineJob<R> engineJob =
        engineJobFactory.build(
            key,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache);
    //建立DecodeJob对象,用来对图片解码
    DecodeJob<R> decodeJob =
        decodeJobFactory.build(
            glideContext,
            model,
            key,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            onlyRetrieveFromCache,
            options,
            engineJob);
    //添加到任务缓存中
    jobs.put(key, engineJob);
    //如今能够不看
    //在获取数据回调进行照片展现时会从新分析到这个方法
    engineJob.addCallback(cb, callbackExecutor);
	//执行任务
    engineJob.start(decodeJob);
    ...  
    return new LoadStatus(cb, engineJob);
  }
复制代码

结合上面的代码和注释,咱们能够知道Engine.load的主要工做:

  • 建立EngineJob对象,用来开启线程
  • 建立DeodeJob对象,用来对照片进行解码
  • 添加回调的对象和线程池
  • 执行任务
执行任务

EngineJob#start

public synchronized void start(DecodeJob<R> decodeJob) {
    this.decodeJob = decodeJob;
	//获取线程池
    GlideExecutor executor = decodeJob.willDecodeFromCache()
        ? diskCacheExecutor
        : getActiveSourceExecutor();
	//执行DecodeJob的run方法
    executor.execute(decodeJob);
  }
复制代码

调用线程池的execute方法,故接下来会执行DecodeJob的run方法

DecodeJob#run

public void run() {
    ....
    try {
      if (isCancelled) {
        notifyFailed();
        return;
      }
	  //重点关注,调用runWrapped
      runWrapped();
    } 
    ....
  }

  private void runWrapped() {
    switch (runReason) {
      case INITIALIZE:
	  	//获取任务场景
        stage = getNextStage(Stage.INITIALIZE);
	    //获取这个场景的执行者
        currentGenerator = getNextGenerator();
	    //重点关注,执行者执行任务
        runGenerators();
        break;
      case SWITCH_TO_SOURCE_SERVICE:
        runGenerators();
        break;
      case DECODE_DATA:
        decodeFromRetrievedData();
        break;
      default:
        throw new IllegalStateException("Unrecognized run reason: " + runReason);
    }
  }
  //获取任务场景
  private Stage getNextStage(Stage current) {
    switch (current) {
      case INITIALIZE:
	  	//若配置的缓存策略容许从资源缓存中读取数据,则返回Stage.RESOURCE_CACHE
        return diskCacheStrategy.decodeCachedResource()
            ? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
      case RESOURCE_CACHE:
	  	//若配置的缓存策略容许从源数据缓存读取数据,则返回Stage.DATA_CACHE
        return diskCacheStrategy.decodeCachedData()
            ? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
      case DATA_CACHE:
        //若只能容许从缓存中读取数据,则直接FINISH,不然返回Stage.SOURCE,表示加载新的资源
        return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
      case SOURCE:
      case FINISHED:
        return Stage.FINISHED;
      default:
        throw new IllegalArgumentException("Unrecognized stage: " + current);
    }
  }

  //获取这个场景的执行者
  private DataFetcherGenerator getNextGenerator() {
    switch (stage) {
      case RESOURCE_CACHE:
	  	// 资源磁盘缓存的执行者
        return new ResourceCacheGenerator(decodeHelper, this);
      case DATA_CACHE:
	  	// 源数据磁盘缓存的执行者
        return new DataCacheGenerator(decodeHelper, this);
      case SOURCE:
	  	// 无缓存, 获取数据的源的执行者
        return new SourceGenerator(decodeHelper, this);
      case FINISHED:
        return null;
      default:
        throw new IllegalStateException("Unrecognized stage: " + stage);
    }
  }

  private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
	// 调用 DataFetcherGenerator.startNext() 执行了请求操做
	//咱们这里主要分析的是无缓存状况,因此这里的DataFetcherGenerator应该是SourceGenerator
    while (!isCancelled && currentGenerator != null
        && !(isStarted = currentGenerator.startNext())) {
      stage = getNextStage(stage);
      currentGenerator = getNextGenerator();

      if (stage == Stage.SOURCE) {
        reschedule();
        return;
      }
    }
    .....
  }
复制代码

怎么执行任务呢?大致上能够分为三个步骤:

  1. 获取任务场景
  2. 获取任务场景的执行者
  3. 执行者执行任务

场景和执行者是一一对应的,因为咱们如今分析的是第一次加载图片,而且没有配置缓存策略,因此对应的任务场景为无缓存状况,与之相对应的执行者就是SourceGenerator对象,因此当执行任务时调用的是SourceGenerator的startNext方法

SourceGenerator#startNext

public boolean startNext() {
    ......
    boolean started = false;
    while (!started && hasNextModelLoader()) {
	  //从DecodeHelper的数据加载集合中, 获取一个数据加载器 
      loadData = helper.getLoadData().get(loadDataListIndex++);
      if (loadData != null
          && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
          || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
        started = true;

		//使用加载器fetcher执行数据加载
		//此fetcher为HttpUrlFetcher对象
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }
    return started;
  }
复制代码
获取数据加载器

首先来看看如何获得数据加载器的集合

DecodeHelper#getLoadData

List<LoadData<?>> getLoadData() {
    if (!isLoadDataSet) {
      isLoadDataSet = true;
      loadData.clear();
	  //从Glide注册的register中获取modelLoaders
      List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
      //遍历modelLoaders
      for (int i = 0, size = modelLoaders.size(); i < size; i++) {
        //此时分析的model为url的string格式,该其中一个实现类为StringLoader 
        ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
		//经过StringLoader构造loadData
		//通过Glide的registry分析后最终会执行HttpGlideUrlLoader的buildLoadData方法
		//最终的loadData封装了HttpUrlFetcher对象
        LoadData<?> current =
            modelLoader.buildLoadData(model, width, height, options);
        if (current != null) {
		  //添加到loadData集合中
          loadData.add(current);
        }
      }
    }
	//最终返回的是含有HttpUrlFetcher对象的loadData集合
    return loadData;
  }
复制代码

咱们来一步步解剖这个方法,首先须要从Glide注册的registry中获取modelLoaders,由于咱们全文以String为例子,因此这里的model将是String类型的。

!!!注意:在注册表中注册的都是ModelLoader的实现ModelLoaderFactory静态工厂类,当调用Registry的getModelLoaders时会调用工厂类中的build方法,这里就不贴出这其中的过程了,如今咱们只须要知道当调用getModelLoaders方法时会调用注册表中对应工厂类的build方法。如今咱们须要回头看看Glide构建时的注册表,看看model为String类型时有那些ModelLoader的静态工厂类,下面只列举几个:

Glide#Glide构造器

registry
		//重点关注StringLoader.StreamFactory()
        .append(String.class, InputStream.class, new StringLoader.StreamFactory())
        .append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())
        .append(
            String.class, AssetFileDescriptor.class, new StringLoader.AssetFileDescriptorFactory())
复制代码

这里咱们以StringLoader.StreamFactory为例子,因为调用了getModelLoaders方法,因此会执行StringLoader.StreamFactory的build方法

StringLoader.StreamFactory()

public static class StreamFactory implements ModelLoaderFactory<String, InputStream> {

    @NonNull
    @Override
    public ModelLoader<String, InputStream> build( @NonNull MultiModelLoaderFactory multiFactory) {
      //从Glide的registry的models注册表能够得知
      //这时候的multiFactory为HttpUriLoader.Factory() 
      //不断追踪下去得知最终参数里返回的是HttpGlideUrlLoader对象
      return new StringLoader<>(multiFactory.build(Uri.class, InputStream.class));
    }
    .....
  }
复制代码

从build方法中,构建了StringLoader对象,可是其中的参数又调用了另一个MultiModelLoaderFactory,这时候咱们须要看会Glide的注册表中,而后找到参数为Uri.class, InputStream.class时构建的MultiModelLoaderFactory对象

Glide#Glide的构造器

registry       
		//重点关注HttpUriLoader.Factory()
        .append(Uri.class, InputStream.class, new HttpUriLoader.Factory())
复制代码

能够发现这时候的MultiModelLoaderFactory对象将会是HttpUriLoader.Factory()类型的,因此咱们还须要看看其中的build方法

HttpUriLoader.Factory#build

public ModelLoader<Uri, InputStream> build(MultiModelLoaderFactory multiFactory) {
      //根据Glide中的registry中的Models注册表能够知道
      //这时候的multiFactory为HttpGlideUrlLoader.Factory()
      return new HttpUriLoader(multiFactory.build(GlideUrl.class, InputStream.class));
    }
复制代码

仍是跟上面同样的步骤,继续查看Glide的注册表,找出参数为GlideUrl.class, InputStream.class的MultiModelLoaderFactory对象

registry    
		//重点关注HttpGlideUrlLoader
        .append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())
复制代码

再看看HttpGlideUrlLoader.Factory的build方法

HttpGlideUrlLoader.Factory#build

public ModelLoader<GlideUrl, InputStream> build(MultiModelLoaderFactory multiFactory) {
      //最终返回的是HttpGlideUrlLoader对象
      return new HttpGlideUrlLoader(modelCache);
    }
复制代码

这里的build方法返回的是HttpGlideUrlLoader类型,因此最终构建StringLoader对象中的参数将是HttpGlideUrlLoader类型的。因而咱们看看StringLoader的构造器的实现。

StringLoader#StringLoader构造器

public StringLoader(ModelLoader<Uri, Data> uriLoader) {
    //此时的uriLoader为HttpGlideUrlLoader对象,赋值给静态成员变量
    this.uriLoader = uriLoader;
  }
复制代码

构建器就是简单的给成员变量赋值,此时的uriLoader为HttpGlideUrlLoader对象。这就是getModelLoaders所作的事,咱们继续分析DecodeHelper的getLoadData方法,当获取到了String的modelLoaders后会遍历每个modelLoader,而后调用modelLoader的buildLoadData来构造loadData对象,这里咱们直接用上面分析获得的StringLoader为例,让咱们看看StringLoader的buildLoadData的实现

StringLoader#buildLoadData

public LoadData<Data> buildLoadData(@NonNull String model, int width, int height, @NonNull Options options) {
    Uri uri = parseUri(model);
    if (uri == null || !uriLoader.handles(uri)) {
      return null;
    }
	//此时的uriLoader为HttpGlideUrlLoader对象
    return uriLoader.buildLoadData(uri, width, height, options);
  }
复制代码

由上面分析咱们已经知道此时StringLoader中的uriLoader为HttpGlideUrlLoader对象,因此会继续调用HttpGlideUrlLoader的buildLoadData方法

HttpGlideUrlLoader

public LoadData<InputStream> buildLoadData(@NonNull GlideUrl model, int width, int height, @NonNull Options options) {
    // GlideUrls memoize parsed URLs so caching them saves a few object instantiations and time
    // spent parsing urls.
    GlideUrl url = model;
    if (modelCache != null) {
      url = modelCache.get(model, 0, 0);
      if (url == null) {
        modelCache.put(model, 0, 0, model);
        url = model;
      }
    }
    int timeout = options.get(TIMEOUT);
	//建立了一个LoadData对象, 而且封装了HttpUrlFetcher对象
    return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
  }
复制代码

其它代码咱们并不须要过多的关注,只须要关注最后的返回值,能够发现最后返回的是封装了HttpUrlFetcher的LoadData对象,这样getLoadData方法获取到的就是封装了HttpUrlFetcher的LoadData对象。让咱们回到SourceGenerator的startNext方法。

SourceGenerator#startNext

public boolean startNext() {
    ......
    boolean started = false;
    while (!started && hasNextModelLoader()) {
	  //最终获取的的对象就是封装了HttpUrlFetcher的LoadData对象
      loadData = helper.getLoadData().get(loadDataListIndex++);
      if (loadData != null
          && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
          || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
        started = true;

		//使用加载器fetcher执行数据加载
		//此fetcher为HttpUrlFetcher对象
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }
    return started;
  }
复制代码

上面已经分析了loadData是封装了HttpUrlFetcher的LoadData对象,因此执行数据加载其实就是调用了HttpUrlFetcher的loadData方法。

执行数据加载

HttpUrlFetcher#loadData

public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
    long startTime = LogTime.getLogTime();
    try {
	  //获取网络图片的输入流 
      InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
	  //将inputStream回调出去,callback为DataCallback
      callback.onDataReady(result);
    }
      ......
  }


  //网络请求代码,利用了HttpURLConnection进行网络请求
  private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl, Map<String, String> headers) throws IOException {
    ......
    //静态工厂模式建立HttpUrlConnection对象
    urlConnection = connectionFactory.build(url);
    for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
      urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
    }
	//设置链接超时时间为2500ms
    urlConnection.setConnectTimeout(timeout);
	//设置读取超时时间为2500ms
    urlConnection.setReadTimeout(timeout);
	//不使用http缓存
    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 (isHttpOk(statusCode)) {
	  //请求成功
      return getStreamForSuccessfulRequest(urlConnection);
    } 
    ......  
  }

  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();
    }
	//最终返回的是图片的InputStream对象,还未开始读取数据
    return stream;
  }
复制代码

能够发现执行数据加载有两个工做,首先是获取数据的输入流,这里采起的是HttpURLConnection进行网络请求,最终获取到的是数据的InputStream对象,记住这时候并未开始读取数据。

返回数据

当获取到输入流后,还须要将这个输入流返回出去,怎么返回呢?

callback.onDataReady(result);
复制代码

能够发现这里使用的是回调的方法将数据的输入流回调出去。此时callbak为DataCallback对象,根据回调的使用咱们知道下一步应该要找到实现DataCallback接口的类,怎么找呢?这时候就须要往回找,调用loadData方法的是在SourceGenerator的startNext方法,因此咱们首选目标就是这个SourceGenerator类

SourceGenerator#onDataReady

class SourceGenerator implements DataFetcherGenerator, DataFetcher.DataCallback<Object>, DataFetcherGenerator.FetcherReadyCallback {
        
  ........
  public void onDataReady(Object data) {
    DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
    if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
      dataToCache = data;
      ....
    } else {
	  //继续回调FetcherReadyCallback的onDataFetcherReady方法,将data回调出去
      cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,
          loadData.fetcher.getDataSource(), originalKey);
    }
  }
}
复制代码

机智如咱们!果真SourceGenerator类实现了DataFetcher.DataCallback这个接口,而且在这个类找到了onDataReady方法,这个方法仍是选择回调,回调了FetcherReadyCallback的onDataFetcherReady方法,因而咱们在往回找,并在心中默念:在哪一个类中调用了SourceGenerator的startNext方法呢?而后你就会发现是在DecodeJob的run方法中调用了startNext这个方法,而后立刻看看DecodeJob是否实现了onDataFetcherReady接口!

DecodeJob#onDataFetcherReady

class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback, Runnable, Comparable<DecodeJob<?>>, Poolable {
        
        
     .......   
	public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) {
    .......
    if (Thread.currentThread() != currentThread) {
      runReason = RunReason.DECODE_DATA;
      callback.reschedule(this);
    } else {
      GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
      try {
	  	//解析获取的数据
        decodeFromRetrievedData();
      } finally {
        GlideTrace.endSection();
      }
    }
  }
  
   private void decodeFromRetrievedData() {
    ....
    try {
	  //获取解析后
      resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    } catch (GlideException e) {
      e.setLoggingDetails(currentAttemptingKey, currentDataSource);
      throwables.add(e);
    }
    if (resource != null) {
	  //通知外界资源获取成功 
      notifyEncodeAndRelease(resource, currentDataSource);
    } else {
      runGenerators();
    }
  }
        
        
}
复制代码

哇!超神了!果真是这样!onDataFetcherReady方法中主要工做有两件:

  1. 解析获取的数据
  2. 返回图片资源

咱们先看看是如何解析数据的

2.5 解析数据

DecodeJob

private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data, DataSource dataSource) throws GlideException {
    try {
      ......

	  //重点关注decodeFromFetcher方法
      Resource<R> result = decodeFromFetcher(data, dataSource);
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        logWithTimeAndKey("Decoded result " + result, startTime);
      }
      return result;
    } 
    ......  
  }

  private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource) throws GlideException {
    //获取当前数据类的解析器LoadPath,此时的data为InputStream对象 
    LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
	//经过解析器来解析数据
    return runLoadPath(data, dataSource, path);
  }

  private <Data, ResourceType> Resource<R> runLoadPath(Data data, DataSource dataSource, LoadPath<Data, ResourceType, R> path) throws GlideException {
    Options options = getOptionsWithHardwareConfig(dataSource);
	//此时的data为InputStream对象,故rewinder为InputStreamRewinder对象
    DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
    try {
      //将数据解析转移到LoadPath.load方法中
      return path.load(
          rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
    } finally {
      rewinder.cleanup();
    }
  }
复制代码

这里的rewinder的获取跟modelLoaders的获取同样须要从新看Glide构建中的注册表registry,在这里再也不详细说明,由于data为InputStream对象,因此rewinder为InputStreamRewinder对象,而后调用LoadPath的load方法实现解析数据

LoadPath

public Resource<Transcode> load(DataRewinder<Data> rewinder, @NonNull Options options, int width, int height, DecodePath.DecodeCallback<ResourceType> decodeCallback) throws GlideException {
    List<Throwable> throwables = Preconditions.checkNotNull(listPool.acquire());
    try {
	  //重点关注
      return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);
    } finally {
      listPool.release(throwables);
    }
  }

  private Resource<Transcode> loadWithExceptionList(DataRewinder<Data> rewinder, @NonNull Options options, int width, int height, DecodePath.DecodeCallback<ResourceType> decodeCallback, List<Throwable> exceptions) throws GlideException {
    Resource<Transcode> result = null;
    //遍历DecodePath集合
    for (int i = 0, size = decodePaths.size(); i < size; i++) {
      DecodePath<Data, ResourceType, Transcode> path = decodePaths.get(i);
      try {
	  	//调用DecodePath.decode真正进行数据解析
        result = path.decode(rewinder, width, height, options, decodeCallback);
      } catch (GlideException e) {
        exceptions.add(e);
      }
      if (result != null) {
        break;
      }
    }

    if (result == null) {
      throw new GlideException(failureMessage, new ArrayList<>(exceptions));
    }

    return result;
  }

复制代码

DecodePath

public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height, @NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
    //获取到Resource<Bitmap>对象 
    Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
	//将资源转化为目标效果,如在构建request时设置的CenterCrop
    Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
	//将数据转化为目标格式,将Resource<Bitmap>转换为LazyBitmapDrawableResource对象
	//可经过LazyBitmapDrawableResource的get获取到BitmapDrawable对象
	//该transcoder为BitmapDrawableTranscoder
    return transcoder.transcode(transformed, options);
  }
复制代码

LoadPath的load方法最终会调用DecodePath的decode来解析数据,DecodePath的decode的主要工做就是获取到Resource对象,而后还要将Resource对象转化成LazyBitmapDrawableResource。考虑到篇幅问题,在这里就不分析如何获得Resource对象,只分析如何将数据转化为目标格式,能够经过Glide构造中的注册表中找出Bitmap转化成Drawable的转化器为BitmapDrawableTranscoder,因此实际上调用了BitmapDrawableTranscoder的transcode来进行转换

BitmapDrawableTranscoder#transcode

public Resource<BitmapDrawable> transcode(@NonNull Resource<Bitmap> toTranscode, @NonNull Options options) {
    //获取LazyBitmapDrawableResource对象 
    return LazyBitmapDrawableResource.obtain(resources, toTranscode);
  }
复制代码

LazyBitmapDrawableResource

public static Resource<BitmapDrawable> obtain( @NonNull Resources resources, @Nullable Resource<Bitmap> bitmapResource) {
    if (bitmapResource == null) {
      return null;
    }
	//建立了一个LazyBitmapDrawableResource对象
    return new LazyBitmapDrawableResource(resources, bitmapResource);
  }
  
  public BitmapDrawable get() {
    //返回一个BitmapDrawable对象
    return new BitmapDrawable(resources, bitmapResource.get());
  }
复制代码

追踪下去能够发现transcode最终会获得一个封装了Resource的对象,而后看LazyBitmapDrawableResource的get方法,能够获得一个BitmapDrawable对象,即目标格式。到这里就成功将数据解析成LazyBitmapDrawableResource对象。

2.6 在主线程中显示图片

既然解析完数据,剩下的工做就是将数据显示出来,因而咱们得从新看回DecodeJob的decodeFromRetrievedData方法

DecodeJob

private void decodeFromRetrievedData() {
    ....
    try {
	  //解析成功后resource为封装了Resource<Bitmap>的LazyBitmapDrawableResource对象
      //可经过get方法获取到BitmapDrawable对象
      resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    } catch (GlideException e) {
      e.setLoggingDetails(currentAttemptingKey, currentDataSource);
      throwables.add(e);
    }
    if (resource != null) {
	  //通知外界资源获取成功 
      notifyEncodeAndRelease(resource, currentDataSource);
    } else {
      runGenerators();
    }
  }

  private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
    .....
    //重点关注
    notifyComplete(result, dataSource);
    ......
    
  }

  private void notifyComplete(Resource<R> resource, DataSource dataSource) {
    setNotifiedOrThrow();
	//回调,注意此时的callback为EngineJob(可回头看Engine中DecodeJob的建立)
    callback.onResourceReady(resource, dataSource);
  }
复制代码

2.6.1 回调数据

嘻嘻,看到最后又来到了咱们熟悉的回调方法,看到这个callback你可能会一脸茫然,这个callback哪一个对象呢?别急,让咱们来一步步分析。

首先先肯定下这个notifyComplete是在DecodeJob类中,所以callback应该是其成员变量,而后咱们得找出赋值的地方

//重点关注倒数第二个参数,callback的类型为CallBack
  DecodeJob<R> init( GlideContext glideContext, Object model, EngineKey loadKey, Key signature, int width, int height, Class<?> resourceClass, Class<R> transcodeClass, Priority priority, DiskCacheStrategy diskCacheStrategy, Map<Class<?>, Transformation<?>> transformations, boolean isTransformationRequired, boolean isScaleOnlyOrNoTransform, boolean onlyRetrieveFromCache, Options options, Callback<R> callback, int order) {
    decodeHelper.init(
        glideContext,
        model,
        signature,
        width,
        height,
        diskCacheStrategy,
        resourceClass,
        transcodeClass,
        priority,
        options,
        transformations,
        isTransformationRequired,
        isScaleOnlyOrNoTransform,
        diskCacheProvider);
    this.glideContext = glideContext;
    this.signature = signature;
    this.priority = priority;
    this.loadKey = loadKey;
    this.width = width;
    this.height = height;
    this.diskCacheStrategy = diskCacheStrategy;
    this.onlyRetrieveFromCache = onlyRetrieveFromCache;
    this.options = options;
    this.callback = callback;
    this.order = order;
    this.runReason = RunReason.INITIALIZE;
    this.model = model;
    return this;
  }
复制代码

很容易的咱们发如今init方法会为callback赋值,这时候得记住callback参数的具体位置为倒数第二个。这时候你会想:哪里会调用DecodeJob的init方法呢?而后揣摩:既然是赋值估计会在构建DecodeJob时候会调用到。因而问题就转换为:上文是在哪一个地方构建了DecodeJob?而后内心默念:DecodeJob是用来执行任务的,因此应该在构建任务的时候会调用!(不过大多数的情形是:脑子里一片空白,压根想不出来,反正笔者在这里就想不出来。因此这时候就能够直接往上找到DecodeJob首次出现的位置),最终是会在Engine的load中找到DecodeJob的构建

Engine#load

public synchronized <R> LoadStatus load(....){
    //重点关注倒数最后一个参数
	DecodeJob<R> decodeJob =
        decodeJobFactory.build(
            glideContext,
            model,
            key,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            onlyRetrieveFromCache,
            options,
            engineJob);

}
    //重点关注最后一个参数
    <R> DecodeJob<R> build(GlideContext glideContext, Object model, EngineKey loadKey, Key signature, int width, int height, Class<?> resourceClass, Class<R> transcodeClass, Priority priority, DiskCacheStrategy diskCacheStrategy, Map<Class<?>, Transformation<?>> transformations, boolean isTransformationRequired, boolean isScaleOnlyOrNoTransform, boolean onlyRetrieveFromCache, Options options, DecodeJob.Callback<R> callback) {
      DecodeJob<R> result = Preconditions.checkNotNull((DecodeJob<R>) pool.acquire());
      return result.init(
          glideContext,
          model,
          loadKey,
          signature,
          width,
          height,
          resourceClass,
          transcodeClass,
          priority,
          diskCacheStrategy,
          transformations,
          isTransformationRequired,
          isScaleOnlyOrNoTransform,
          onlyRetrieveFromCache,
          options,
          callback,
          creationOrder++);
    }
  }
复制代码

在上面的代码中首先调用了DecodeJobFactory的build方法来构建DecodeJob,DecodeJobFactory是Engine的内部类,而后接着看DecodeJobFactory的build方法,哇!跟咱们想的彻底同样!build方法中调用了DecodeJob的init方法,找到后可别忘了咱们的任务是干吗的!找到callback的值,因而看回build的callback的参数位置,在最后一个,而后往回看Engine的load中调用build的最后一个参数!engineJob!没错最后找到的callback的类型应该是EngineJob类型的,其实EngineJob是实现了DecodeJob.Callback接口的。因此接下来就会回调EngineJob的onResourceReady方法

EngineJob#onResourceReady

public void onResourceReady(Resource<R> resource, DataSource dataSource) {
    synchronized (this) {
      this.resource = resource;
      this.dataSource = dataSource;
    }
	//重点关注
    notifyCallbacksOfResult();
  }

  void notifyCallbacksOfResult() {
    ResourceCallbacksAndExecutors copy;
    Key localKey;
    EngineResource<?> localResource;
    synchronized (this) {
      ......

	  //重点关注cbs的类型
	  //查找cbs里面的类型
      copy = cbs.copy();
      .....
    }
    //通知上层Engine的任务完成了
    listener.onEngineJobComplete(this, localKey, localResource);

    for (final ResourceCallbackAndExecutor entry : copy) {
	  //回调给ImageViewTarget来展现资源
      entry.executor.execute(new CallResourceReady(entry.cb));
    }
    decrementPendingCallbacks();
  }
复制代码

2.6.2 回到主线程

又到了肯定参数类型的时刻了,赶忙召唤福尔摩斯上线!首先咱们先肯定EngineJob的onResourceReady方法中最重要的代码片

for (final ResourceCallbackAndExecutor entry : copy) {
	  //回调给ImageViewTarget来展现资源
      entry.executor.execute(new CallResourceReady(entry.cb));
    }
复制代码

在肯定分析线程池的execute的方法前,咱们须要作的事有:

  • 肯定entry.executor类型
  • 肯定entry.cb类型

如今咱们知道entry为ResourceCallbackAndExecutor方法,因此咱们来看看这个类以及构造器

ResourceCallbackAndExecutor

static final class ResourceCallbackAndExecutor {
    final ResourceCallback cb;
    final Executor executor;

    ResourceCallbackAndExecutor(ResourceCallback cb, Executor executor) {
      this.cb = cb;
      this.executor = executor;
    }
  }
复制代码

能够发现executor和cb都是ResourceCallbackAndExecutor中的成员变量,在构造时被赋值,因此咱们须要找到构造ResourceCallbackAndExecutor对象的地方,天然而然咱们会锁定上面copy这个变量

EngineJob

final ResourceCallbacksAndExecutors cbs = new ResourceCallbacksAndExecutors();

void notifyCallbacksOfResult() {
    ResourceCallbacksAndExecutors copy;
    Key localKey;
    EngineResource<?> localResource;
    synchronized (this) {
      ......

	  //重点关注cbs的类型
	  //查找cbs里面的类型
      copy = cbs.copy();
      .....
    }
    .....
  }

    ResourceCallbacksAndExecutors copy() {
      return new ResourceCallbacksAndExecutors(new ArrayList<>(callbacksAndExecutors));
    }

     
    //cbs赋值的地方
    synchronized void addCallback(final ResourceCallback cb, Executor callbackExecutor) {
    stateVerifier.throwIfRecycled();
	//此时的cb为singleRequest类型,其实现了ResourceCallback接口
	//callbackExecutor就是绑定了主线程Handler的线程池
	//cbs的类型为ResourceCallbacksAndExecutors
	//add的内部实现就是建立ResourceCallbacksAndExecutor并将cb,callbackExecutor赋值到其成员变量
    //而后再add到cbs中 
    cbs.add(cb, callbackExecutor);
    ......
     
  }


    void add(ResourceCallback cb, Executor executor) {
      callbacksAndExecutors.add(new ResourceCallbackAndExecutor(cb, executor));
    }

复制代码

让咱们看看copy赋值调用的地方,就是调用了ResourceCallbacksAndExecutors类型的cbs的copy方法,copy其实就是建立了ResourceCallbacksAndExecutor集合,这个集合其实就是cbs,咱们还须要找到cbs赋值的地方,找半天后你会发如今addCallback方法中会找到cbs的add方法,add方法的内部实现其实就是建立ResourceCallbacksAndExecutor并将cb,callbackExecutor赋值到其成员变量中,因此咱们还得肯定add方法的两个参数是什么?不知道你是否还有印象,当初在构建任务时咱们有专门提到过这个addCallback方法,让咱们从新看看Engine的load方法。

Engine#load

....
    //调用addCallback()注册了一个ResourceCallback
	//这里的cb是load方法的倒数第二个参数,load是在singleRequest的onSizeReady()调用的
	//查看后cb为singleRequest类型
	//从新看回EngineJob的addCallback方法
    engineJob.addCallback(cb, callbackExecutor);
	//在子线程中执行DecodeJob的run方法
    engineJob.start(decodeJob);
复制代码

要想肯定cb和callbackExecutor的类型,咱们还须要一步一步往回走

//特别关注最后两个参数
  public synchronized <R> LoadStatus load( GlideContext glideContext, Object model, Key signature, int width, int height, Class<?> resourceClass, Class<R> transcodeClass, Priority priority, DiskCacheStrategy diskCacheStrategy, Map<Class<?>, Transformation<?>> transformations, boolean isTransformationRequired, boolean isScaleOnlyOrNoTransform, Options options, boolean isMemoryCacheable, boolean useUnlimitedSourceExecutorPool, boolean useAnimationPool, boolean onlyRetrieveFromCache, ResourceCallback cb, Executor callbackExecutor) 复制代码

SingleRequest#onSizeReady

loadStatus =
    	//重点关注倒数第二个参数,传入的是this,即SingleRequest对象,其实现了ResourceCallback接口
    	//重点关注倒数第一个参数,传入有绑定主线程的Handle的r线程池callbackExectuter
        engine.load(
            glideContext,
            model,
            requestOptions.getSignature(),
            this.width,
            this.height,
            requestOptions.getResourceClass(),
            transcodeClass,
            priority,
            requestOptions.getDiskCacheStrategy(),
            requestOptions.getTransformations(),
            requestOptions.isTransformationRequired(),
            requestOptions.isScaleOnlyOrNoTransform(),
            requestOptions.getOptions(),
            requestOptions.isMemoryCacheable(),
            requestOptions.getUseUnlimitedSourceGeneratorsPool(),
            requestOptions.getUseAnimationPool(),
            requestOptions.getOnlyRetrieveFromCache(),
            this,
            callbackExecutor);
复制代码

SingleRequest的onSizeReady中咱们肯定了cb的类型为SingleRequest对象,另一个参数的话因为篇幅缘由就不一一贴出代码了(都是上文贴过的代码),你能够直接从onSizeReady方法往回看,上面的注释也会提到,最后你会发现这个callbackExecutor其实就是咱们一开始提到的含有绑定主线程Handler的线程池。让咱们回到最初的地方

EngineJob#onResourceReady

for (final ResourceCallbackAndExecutor entry : copy) {
	  //回调给ImageViewTarget来展现资源
       //entry.cb为singleRequest类型类型
	   //entry.executor就是含有绑定了主线程的Handler的线程池,即MAIN_THREAD_EXECUTOR
      entry.executor.execute(new CallResourceReady(entry.cb));
    }
复制代码

因此咱们来看看Executors的mainThreadExecutor方法(忘记的从新看上面的2.2)

private static final Executor MAIN_THREAD_EXECUTOR =
      new Executor() {
       //绑定主线程的Looper
        private final Handler handler = new Handler(Looper.getMainLooper());

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

public static Executor mainThreadExecutor() {
    return MAIN_THREAD_EXECUTOR;
  }
复制代码

根据Handler机制的相关知识,当调用MAIN_THREAD_EXECUTOR的execute方法后将会在主线程中执行CallResourceReady对象的run方法。因此咱们看看CallResourceReady的run方法

2.6.3 显示图片

EngineJob.CallResourceReady#run

public void run() {
      synchronized (EngineJob.this) {
        if (cbs.contains(cb)) {
          // Acquire for this particular callback.
          engineResource.acquire();
		  //重点关注,此时cb为SingleRequest对象
          callCallbackOnResourceReady(cb);
          removeCallback(cb);
        }
        decrementPendingCallbacks();
      }
    }
  }

  synchronized void callCallbackOnResourceReady(ResourceCallback cb) {
    try {
      //回调,将目标数据回调出去
      //此时的cb为singleRequest类型
      cb.onResourceReady(engineResource, dataSource);
    } catch (Throwable t) {
      throw new CallbackException(t);
    }
  }
复制代码

看到这是否是很开心(实际头皮发麻)!又来到了咱们熟悉的回调了,此时的cb是SingleRequest类型,咱们已经在上文分析过了。因此会调用SingleRequest的onResourceReady方法

SingleRequest#onResourceReady

public synchronized void onResourceReady(Resource<?> resource, DataSource dataSource) {
    .......
    //重点关注
    onResourceReady((Resource<R>) resource, (R) received, dataSource);
  }

  private synchronized void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
    //第一次加载
    boolean isFirstResource = isFirstReadyResource();
    status = Status.COMPLETE;
    this.resource = resource;

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

    isCallingCallbacks = true;
    try {
      boolean anyListenerHandledUpdatingTarget = false;
	  //若是在使用时设置listener的话,就会回调其中的onResourceReady
      if (requestListeners != null) {
        for (RequestListener<R> listener : requestListeners) {
          anyListenerHandledUpdatingTarget |=
              listener.onResourceReady(result, model, target, dataSource, isFirstResource);
        }
      }
      anyListenerHandledUpdatingTarget |=
          targetListener != null
              && targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);
      
      if (!anyListenerHandledUpdatingTarget) {
        Transition<? super R> animation =
            animationFactory.build(dataSource, isFirstResource);

        //展现照片
	    //此时的target为DrawableImageViewTarget
        target.onResourceReady(result, animation);
      }
    } finally {
      isCallingCallbacks = false;
    }
    //通知加载成功
    notifyLoadSuccess();
  }
复制代码

这里咱们只须要关注target.onResourceReady(result, animation)这句代码,target对象为DrawableImageViewTarget,因此会调用DrawableImageViewTarget的onResourceReady方法,可是由于DrawableImageViewTarget是没有onResourceReady这个方法的,因此应该是在其父类ImageViewTarget中

ImageViewTarget

public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
     //是否有动画效果 
    if (transition == null || !transition.transition(resource, this)) {
	  //重点关注,静态图 
      setResourceInternal(resource);
    } else {
      //gif 
      maybeUpdateAnimatable(resource);
    }
  }

  private void setResourceInternal(@Nullable Z resource) {
    //调用setResource来展现照片
    setResource(resource);
    maybeUpdateAnimatable(resource);
  }

  //此方法为抽象方法,由子类实现,因为分析的是静态图,故实现的子类应该为DrawableImageViewTarget
  protected abstract void setResource(@Nullable Z resource);
复制代码

这里咱们以正常的静态图为例子,因此接下来会调用setResourceInternal(resource)方法,而后继续调用setResource(resource)方法来展现图片,setResource在ImageViewTarget为抽象方法,因此咱们继续看回子类DrawableImageViewTarget的实现

DrawableImageViewTarget#setResource

protected void setResource(@Nullable Drawable resource) {
    //成功展现照片
    view.setImageDrawable(resource);
  }
复制代码

哇!看到这里眼泪估计又要流下来了,没错setResource很简单,就是直接将照片显示出来!

3. 小结

into方法算的上是整个Glide图片加载流程中逻辑最复杂的一部曲了,代码量多,相对应的工做量也是超级多的,既当爹又当妈,既要网络获取数据,又要解析并显示数据。整理后其主要工做以下图:

总结

Glide源码阅读仍是花了很长时间,首先阅读了几篇Glide3.x版本的文章和Glide3.7的源码,而后又阅读了Glide4.9的文章和源码,最后再本身总结。阅读完Glide4.9加载流程的源码给个人感觉就是这回调是真的多,并且找回调的参数还挺费时间的。不过总体而言,心里只有一句话,“Glide牛逼!”,用起来只有一行代码,实际内部处理逻辑是多么的复杂以及到位,也足以见得Glide的功能有多强大了。可是Glide功能的强大不只仅体如今图片加载流程,还有其强大的缓存策略,让咱们继续领略Glide的强大: Glide 4.9源码解析-缓存策略

参考博客: