Glide源碼(二)

接著上一篇扣墩,with方法獲取到RequestManager 對象,它實現(xiàn)了LifecycleListener接口办绝,這意味著试伙,頁面生命周期的觸發(fā)會通知到RequestManager 類,但根據(jù)上一篇分析勤哗,在此之前薛闪,它必須先被添加到ActivityFragmentLifecycle的成員變量lifecycleListeners 集合中 ,我們先看它的構(gòu)造方法俺陋。

public class RequestManager implements LifecycleListener,
    ModelTypes<RequestBuilder<Drawable>> {

  private final ConnectivityMonitor connectivityMonitor;
  private final Handler mainHandler = new Handler(Looper.getMainLooper());
  private final CopyOnWriteArrayList<RequestListener<Object>> defaultRequestListeners;
  
  private final Runnable addSelfToLifecycle = new Runnable() {
    @Override
    public void run() {
      lifecycle.addListener(RequestManager.this);
    }
  };
  public RequestManager(
      @NonNull Glide glide, @NonNull Lifecycle lifecycle,
      @NonNull RequestManagerTreeNode treeNode, @NonNull Context context) {
    this(
        glide,
        lifecycle,
        treeNode,
        new RequestTracker(),
        glide.getConnectivityMonitorFactory(),
        context);
  }

  RequestManager(
      Glide glide,
      Lifecycle lifecycle,
      RequestManagerTreeNode treeNode,
      RequestTracker requestTracker,
      ConnectivityMonitorFactory factory,
      Context context) {
    this.glide = glide;
    this.lifecycle = lifecycle;
    this.treeNode = treeNode;
    this.requestTracker = requestTracker;
    this.context = context;
    //網(wǎng)絡(luò)監(jiān)聽器
    connectivityMonitor =
        factory.build(
            context.getApplicationContext(),
            new RequestManagerConnectivityListener(requestTracker));

    //后臺線程豁延,切到主線程中添加
    if (Util.isOnBackgroundThread()) {
      mainHandler.post(addSelfToLifecycle);
    } else {
      //添加自己到ActivityFragmentLifecycle的集合中
      lifecycle.addListener(this);
    }
    //添加網(wǎng)絡(luò)監(jiān)聽器
    lifecycle.addListener(connectivityMonitor);

    defaultRequestListeners =
        new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
    setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());

    //保存到glide的成員列表中
    glide.registerRequestManager(this);
  }

}

可以看出昙篙,ConnectivityMonitor 也實現(xiàn)了LifecycleListener接口,因為它也被添加到lifecycleListeners 集合中诱咏,跟隨Framgent的生命周期回調(diào)苔可。

獲取到RequestManager對象后,將調(diào)用load方法袋狞。

public class RequestManager implements LifecycleListener,
    ModelTypes<RequestBuilder<Drawable>> {

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

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

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

    //轉(zhuǎn)碼后的類型為Bitmap.class
    public RequestBuilder<Bitmap> asBitmap() {
      return as(Bitmap.class).apply(DECODE_TYPE_BITMAP);
    }

    //轉(zhuǎn)碼后的類型為Drawable.class
    public RequestBuilder<Drawable> asDrawable() {
      return as(Drawable.class);
    }

    //獲取RequestBuilder
    public <ResourceType> RequestBuilder<ResourceType> as(
    @NonNull Class<ResourceType> resourceClass) {
    // resourceClass 就是最終要轉(zhuǎn)碼的類型
      return new RequestBuilder<>(glide, this, resourceClass, context);
    }

}

適配不同資源的加載焚辅,load有多個重載方法,他們最終都通過as方法來獲取一個RequestBuilder對象苟鸯,后面一連串的鏈式調(diào)用同蜻,都將通過這個對象的方法作為入口來執(zhí)行。和RequestManager 的load方法一樣早处,RequestBuilder的load也有許多重載方法湾蔓,我們以網(wǎng)絡(luò)地址加載為例來做分析掌实。

public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
    implements Cloneable,
    ModelTypes<RequestBuilder<TranscodeType>> {

  private Object model;
  private boolean isModelSet;

  //加載網(wǎng)絡(luò)地址
  public RequestBuilder<TranscodeType> load(@Nullable String string) {
      return loadGeneric(string);
    }

  //將地址封裝成model
  private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
    this.model = model;
    isModelSet = true;
    return this;
  }


}

在執(zhí)行請求前拱层,所有數(shù)據(jù)源都會被封裝成一個model對象碎绎,它是Object類型的度硝。

load方法調(diào)用完成肝谭,便獲得的一個RequestBuilder對象二跋,接著通過它調(diào)用into方法裆站。

public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
    implements Cloneable,
    ModelTypes<RequestBuilder<TranscodeType>> {

    ......

  public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    Util.assertMainThread();
    Preconditions.checkNotNull(view);

    BaseRequestOptions<?> requestOptions = this;
    if (!requestOptions.isTransformationSet()
        && requestOptions.isTransformationAllowed()
        && view.getScaleType() != null) {
      // 根據(jù)裁剪配置options
      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:
      }
    }
  
    return into(
        glideContext.buildImageViewTarget(view, transcodeClass),
        null,
        requestOptions,
        Executors.mainThreadExecutor());
      }

}

會根據(jù)我們在ImageView中設(shè)置的ScaleType類型溯职,給requestOptions 配置裁剪類型烂瘫。最后的into重載方法中媒熊,將調(diào)用buildImageViewTarget根據(jù)轉(zhuǎn)碼的類型來生成一個 ViewTarget,這個方法定義在GlideContext中坟比。

public class GlideContext extends ContextWrapper {
      ......
  private final ImageViewTargetFactory imageViewTargetFactory;
     ......

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

}

在上一篇分析Glide的初始化時芦鳍,ImageViewTargetFactory 這個圖片顯示目標對象工廠,已經(jīng)在構(gòu)造方法中創(chuàng)建出來了温算,同時還創(chuàng)建了GlideContext 對象怜校,將ImageViewTargetFactory 傳遞給它。

public class ImageViewTargetFactory {
  @NonNull
  @SuppressWarnings("unchecked")
  public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
      @NonNull Class<Z> clazz) {
    //Bitmap
    if (Bitmap.class.equals(clazz)) {
      return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
    //是否Drawable或其子類
    } 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)");
    }
  }
}

ViewTarget的子類有兩種注竿,在上面的RequestManager 類中雖然有多個as方法茄茁,但最終的轉(zhuǎn)碼類型只會有兩類,即Bitmap類型或Drawable及其子類類型巩割,我們加載網(wǎng)絡(luò)地址裙顽,這里的ViewTarget將使用DrawableImageViewTarget,它繼承ImageViewTarget宣谈,持有ImageView對象愈犹。

public class DrawableImageViewTarget extends ImageViewTarget<Drawable> {
  public DrawableImageViewTarget(ImageView view) {
    super(view);
  }

  @SuppressWarnings({"unused", "deprecation"})
  @Deprecated
  public DrawableImageViewTarget(ImageView view, boolean waitForLayout) {
    super(view, waitForLayout);
  }

  //設(shè)置圖片
  @Override
  protected void setResource(@Nullable Drawable resource) {
    view.setImageDrawable(resource);
  }
}

看到setResource這個方法我們可以猜到,最終圖片被顯示到ImageView中,將通過它來完成漩怎。我們先回到RequestManager 重載的into方法勋颖。

public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
    implements Cloneable,
    ModelTypes<RequestBuilder<TranscodeType>> {


  private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> options,
      Executor callbackExecutor) {
  
    //這里的Target就是DrawableImageViewTarget了
    Preconditions.checkNotNull(target);

    //是否設(shè)置了數(shù)據(jù)源,也就是url勋锤,在load中isModelSet已置為true
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

    //Request類是一個接口饭玲,他抽象了Glide加載圖片請求
    Request request = buildRequest(target, targetListener, options, callbackExecutor);
    //獲取上一次的Request
    Request previous = target.getRequest();

    // 當前的target里有Request存在
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
      //回收剛新建的Request對象
      request.recycle();
      if (!Preconditions.checkNotNull(previous).isRunning()) {
              //執(zhí)行當前的Request
              previous.begin();
      }
      //結(jié)束
      return target;
    }
    //清除target
    requestManager.clear(target);
    //Target中設(shè)置request
    target.setRequest(request);
    //執(zhí)行request
    requestManager.track(target, request);

    return target;
  }
}

Request用來發(fā)出加載圖片的請求,通過buildRequest來構(gòu)建叁执,然后將通過RequestManager對象來執(zhí)行這個請求茄厘。我們先看構(gòu)建過程。

public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
    implements Cloneable,
    ModelTypes<RequestBuilder<TranscodeType>> {


    private Request buildRequest(
      Target<TranscodeType> target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> requestOptions,
      Executor callbackExecutor) {
    return buildRequestRecursive(
        target,
        targetListener,
         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) {

    // 如果配置了錯誤請求則新建錯誤請求協(xié)調(diào)器
    ErrorRequestCoordinator errorRequestCoordinator = null;
    if (errorBuilder != null) {
      errorRequestCoordinator = new ErrorRequestCoordinator(parentCoordinator);
      parentCoordinator = errorRequestCoordinator;
    }

  // 構(gòu)造目標請求
    Request mainRequest =
        buildThumbnailRequestRecursive(
            target,
            targetListener,
            parentCoordinator,
            transitionOptions,
            priority,
            overrideWidth,
            overrideHeight,
            requestOptions,
            callbackExecutor);

    //如果沒有配置錯誤請求則結(jié)束谈宛,否則繼續(xù)下面代碼構(gòu)建錯誤時的備用請求
    if (errorRequestCoordinator == null) {
      return mainRequest;
    }

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

  // 錯誤時的備用請求
    Request errorRequest =
        errorBuilder.buildRequestRecursive(
            target,
            targetListener,
            errorRequestCoordinator,
            errorBuilder.transitionOptions,
            errorBuilder.getPriority(),
            errorOverrideWidth,
            errorOverrideHeight,
            errorBuilder,
            callbackExecutor);
    errorRequestCoordinator.setRequests(mainRequest, errorRequest);
    return errorRequestCoordinator;
  }


    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) {
 
    if (thumbnailBuilder != null) {
          if (isThumbnailBuilt) {
        throw new IllegalStateException("You cannot use a request as both the main request and a "
            + "thumbnail, consider using clone() on the request(s) passed to thumbnail()");
      }

    // 設(shè)置 transitionOptions
      TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions =
          thumbnailBuilder.transitionOptions;

      if (thumbnailBuilder.isDefaultTransitionOptionsSet) {
        thumbTransitionOptions = transitionOptions;
      }

      //優(yōu)先級
      Priority thumbPriority = thumbnailBuilder.isPrioritySet()
          ? thumbnailBuilder.getPriority() : getThumbnailPriority(priority);

      //圖片尺寸
      int thumbOverrideWidth = thumbnailBuilder.getOverrideWidth();
      int thumbOverrideHeight = thumbnailBuilder.getOverrideHeight();
      if (Util.isValidDimensions(overrideWidth, overrideHeight)
          && !thumbnailBuilder.isValidOverride()) {
        thumbOverrideWidth = requestOptions.getOverrideWidth();
        thumbOverrideHeight = requestOptions.getOverrideHeight();
      }
      
      // 縮略圖請求協(xié)調(diào)器
      ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);

      // 目標請求
      Request fullRequest =
          obtainRequest(
              target,
              targetListener,
              requestOptions,
              coordinator,
              transitionOptions,
              priority,
              overrideWidth,
              overrideHeight,
              callbackExecutor);
      isThumbnailBuilt = true;

      // 縮略圖的請求 
      Request thumbRequest =
          thumbnailBuilder.buildRequestRecursive(
              target,
              targetListener,
              coordinator,
              thumbTransitionOptions,
              thumbPriority,
              thumbOverrideWidth,
              thumbOverrideHeight,
              thumbnailBuilder,
              callbackExecutor);
      isThumbnailBuilt = false;
      coordinator.setRequests(fullRequest, thumbRequest);
      return coordinator;
    } else if (thumbSizeMultiplier != null) {
      ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
      Request fullRequest =
          obtainRequest(
              target,
              targetListener,
              requestOptions,
              coordinator,
              transitionOptions,
              priority,
              overrideWidth,
              overrideHeight,
              callbackExecutor);
      BaseRequestOptions<?> thumbnailOptions =
          requestOptions.clone().sizeMultiplier(thumbSizeMultiplier);

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

      coordinator.setRequests(fullRequest, thumbnailRequest);
      return coordinator;
    } else {
      // 沒有縮略圖時次哈,構(gòu)造請求
      return obtainRequest(
          target,
          targetListener,
          requestOptions,
          parentCoordinator,
          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) {
    return SingleRequest.obtain(
        context,
        glideContext,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        glideContext.getEngine(),
        transitionOptions.getTransitionFactory(),
        callbackExecutor);
  }
}

構(gòu)建目標Request請求的代碼比較長,如果我們配置了縮略圖要求吆录,它將構(gòu)建縮略圖請求窑滞,并和目標請求一起放入到協(xié)調(diào)器中。ThumbnailRequestCoordinator 請求協(xié)調(diào)器径筏,可以用來協(xié)調(diào)各請求的順序葛假。

我們只分析目標請求流程障陶,也就是沒有設(shè)置縮略圖的情況滋恬。由obtain靜態(tài)方法可以看到,最終獲得的目標Request對象就是SingleRequest抱究,它封裝了圖片請求需要的各個成員恢氯。

public final class SingleRequest<R> implements Request,
    SizeReadyCallback,
    ResourceCallback,
    FactoryPools.Poolable {
    
    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();

    //創(chuàng)建SingleRequest對象
    if (request == null) {
      request = new 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");
    }
  }

}

目標Request已經(jīng)構(gòu)建完成,再回到requestManager.track(target, request)這行代碼鼓寺,看Request如何被發(fā)出去的勋拟。它通過RequestManager來調(diào)用。

public class RequestManager implements LifecycleListener,
    ModelTypes<RequestBuilder<Drawable>> {
  
    //請求追蹤器
  private final RequestTracker requestTracker;

  public RequestManager(
      @NonNull Glide glide, @NonNull Lifecycle lifecycle,
      @NonNull RequestManagerTreeNode treeNode, @NonNull Context context) {
    this(
        glide,
        lifecycle,
        treeNode,
        new RequestTracker(),//創(chuàng)建請求追蹤器
        glide.getConnectivityMonitorFactory(),
        context);
  }

  synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
    targetTracker.track(target);
    // 開始請求
    requestTracker.runRequest(request);
  }


}

任務(wù)被移交給了RequestTracker請求追蹤器進行追蹤妈候,這個對象RequestManager在構(gòu)造時創(chuàng)建的敢靡。

public class RequestTracker {
   private final Set<Request> requests =
      Collections.newSetFromMap(new WeakHashMap<Request, Boolean>());
  private final List<Request> pendingRequests = new ArrayList<>();
  private boolean isPaused;

  //執(zhí)行請求任務(wù)
  public void runRequest(@NonNull Request request) {
    //添加到集合中
    requests.add(request);
    //沒有暫停
    if (!isPaused) {
      //開始請求
      request.begin();
    } else {
    //被暫停則清理掉某些資源
      request.clear();
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Paused, delaying request");
      }
      //添加到待處理列表
      pendingRequests.add(request);
    }

  }

如果任務(wù)此時被暫停了,那么將清理掉某些資源苦银,但這個Request 還可以通過begin()方法來重新發(fā)出啸胧,所以被保存到pendingRequests待處理
列表中。

上面說過幔虏,所有圖片請求相關(guān)的成員都被封裝到Request(SingleRequest )對象中纺念,它將指定Target去加載自己的資源。

public final class SingleRequest<R> implements Request,
    SizeReadyCallback,
    ResourceCallback,
    FactoryPools.Poolable {

  public synchronized void begin() {
    assertNotCallingCallbacks();
    stateVerifier.throwIfRecycled();
    startTime = LogTime.getLogTime();
    //即地址為null
    if (model == null) {
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
        width = overrideWidth;
        height = overrideHeight;
      }
   
      int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
      //加載出錯處理
      onLoadFailed(new GlideException("Received null model"), logLevel);
      return;
    }

    if (status == Status.RUNNING) {
      throw new IllegalArgumentException("Cannot restart a running request");
    }

    // 請求加載完成后回調(diào)
    if (status == Status.COMPLETE) {
      onResourceReady(resource, DataSource.MEMORY_CACHE);
      return;
    }

    status = Status.WAITING_FOR_SIZE;
  // 如果指定了寬高想括,直接回調(diào) onSizeReady
    if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
      onSizeReady(overrideWidth, overrideHeight);
    } else {
    // 根據(jù) target 的寬高來加載圖片的寬高
      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));
    }

  }
  
public synchronized void onSizeReady(int width, int height) {
    stateVerifier.throwIfRecycled();
    if (IS_VERBOSE_LOGGABLE) {
      logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
    }
    if (status != Status.WAITING_FOR_SIZE) {
      return;
    }
    status = Status.RUNNING;

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

    if (IS_VERBOSE_LOGGABLE) {
      logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
    }

    //加載圖片并返回狀態(tài)
    loadStatus =
        engine.load(
            glideContext,
            model,
            requestOptions.getSignature(),
            this.width,
            this.height,
            requestOptions.getResourceClass(),
            transcodeClass,
            priority,
            requestOptions.getDiskCacheStrategy(),
            requestOptions.getTransformations(),
            requestOptions.isTransformationRequired(),
            requestOptions.isScaleOnlyOrNoTransform(),
            requestOptions.getOptions(),
            requestOptions.isMemoryCacheable(),
            requestOptions.getUseUnlimitedSourceGeneratorsPool(),
            requestOptions.getUseAnimationPool(),
            requestOptions.getOnlyRetrieveFromCache(),
            this,
            callbackExecutor);
    
    if (status != Status.RUNNING) {
      loadStatus = null;
    }
    if (IS_VERBOSE_LOGGABLE) {
      logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
    }
  }

}

加載分兩種情況,如果指定了一個固定的寬高瑟蜈,就會直接執(zhí)行onSizeReady()方法烟逊。如果沒指定的話渣窜,調(diào)用target.getSize()方法。這個target.getSize()方法宪躯,它會根據(jù)ImageView布局設(shè)置的寬高图毕,算出圖片應(yīng)該顯示的寬高。計算完之后眷唉,它也會調(diào)用onSizeReady()方法予颤。

但請求加載流程還不是在這個類中執(zhí)行的,它把這個任務(wù)交給了Engine對象來處理冬阳,這個對象是在GlideBuilder的build方法中創(chuàng)建的蛤虐,我們前面分析過,在build方法中還創(chuàng)建了幾個緩存池和以及復用池肝陪,這些池子都封裝到了Engine對象中驳庭。并且在隨后的Glide構(gòu)造方法中構(gòu)建GlideContext對象時,將其保存到這個上下文中氯窍。

public class Engine implements EngineJobListener,
    MemoryCache.ResourceRemovedListener,
    EngineResource.ResourceListener {




    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) {


    long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;

    // 創(chuàng)建資源索引 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 (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from active resources", startTime, key);
      }
      return null;
    }
    //從緩存中獲取
    EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
    if (cached != null) {
      cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from cache", startTime, key);
      }
      return null;
    }
    // 獲取已經(jīng)存在的加載任務(wù) 饲常,onlyRetrieveFromCache 參數(shù)表示是否只加載緩存中的數(shù)據(jù)
    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
      // 添加 SingleRequest 回調(diào)對象 
      current.addCallback(cb, callbackExecutor);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Added to existing load", startTime, key);
      }
      return new LoadStatus(cb, current);
    }

    // 構(gòu)造 EngineJob 對象,用于啟動解碼任務(wù)
    EngineJob<R> engineJob =
        engineJobFactory.build(
            key,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache);

    //構(gòu)建解碼器并初始化
    DecodeJob<R> decodeJob =
        decodeJobFactory.build(
            glideContext,
            model,
            key,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            onlyRetrieveFromCache,
            options,
            engineJob);
    // 緩存加載任務(wù)
    jobs.put(key, engineJob);
    // 添加 SingleRequest 回調(diào)對象 
    engineJob.addCallback(cb, callbackExecutor);
    // 執(zhí)行解碼任務(wù)
    engineJob.start(decodeJob);

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

}

既然Engine 封裝了許多緩存池狼讨,那么做網(wǎng)絡(luò)請求前贝淤,必然先看緩存有沒有。buildKey方法將幾個參數(shù)封裝成EngineKey 政供,根據(jù)這個Key 來獲取內(nèi)存緩存數(shù)據(jù)播聪,如果存在,則直接回調(diào)成功布隔,如果不存在离陶,則新建EngineJob 對象和DecodeJob解碼器,DecodeJob實現(xiàn)了Runnable衅檀,通過EngineJob 對象調(diào)用start來啟動招刨。

緩存的獲取這里先不分析,我們分析首次加載哀军,即沒有緩存的情況沉眶。那么,緊接著的工作又傳遞給了EngineJob 對象排苍,它會通過線程池來開啟DecodeJob這個Runnable沦寂。

class EngineJob<R> implements DecodeJob.Callback<R>,
    Poolable {

    //通過線程池啟動圖片加載任務(wù)
  public synchronized void start(DecodeJob<R> decodeJob) {
    this.decodeJob = decodeJob;
    GlideExecutor executor = decodeJob.willDecodeFromCache()
        ? diskCacheExecutor
        : getActiveSourceExecutor();
    executor.execute(decodeJob);
  }

}

很顯然,GlideExecutor 是Glide自定義的Executor淘衙,它內(nèi)部實現(xiàn)了線程池传藏。因此,我們直接看DecodeJob的run方法。

class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
    Runnable,
    Comparable<DecodeJob<?>>,
    Poolable {
  //加載輔助類
  private final DecodeHelper<R> decodeHelper = new DecodeHelper<>();


    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;//初始化RunReason為INITIALIZE
    this.model = model;
    return this;
  }

   public void run() {
   
    GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)", model);
  
    DataFetcher<?> localFetcher = currentFetcher;
    try {
      if (isCancelled) {
        notifyFailed();
        return;
      }
      //進入runWrapped
      runWrapped();
    } catch (CallbackException e) {
       throw e;
    } catch (Throwable t) {
 
      if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "DecodeJob threw unexpectedly"
            + ", isCancelled: " + isCancelled
            + ", stage: " + stage, t);
      }

      if (stage != Stage.ENCODE) {
        throwables.add(t);
        notifyFailed();
      }
      if (!isCancelled) {
        throw t;
      }
      throw t;
    } finally {
      if (localFetcher != null) {
        localFetcher.cleanup();
      }
      GlideTrace.endSection();
    }
  }

   private void runWrapped() {
    switch (runReason) {
      case INITIALIZE:
        stage = getNextStage(Stage.INITIALIZE);
        currentGenerator = getNextGenerator();
        runGenerators();
        break;
      case SWITCH_TO_SOURCE_SERVICE:
        runGenerators();
        break;
      case DECODE_DATA:
        decodeFromRetrievedData();
        break;
      default:
        throw new IllegalStateException("Unrecognized run reason: " + runReason);
    }
  }

  //獲取不同類型加載器
  private 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);
    }
  }

  //根據(jù)不同加載器獲取圖片
  private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    while (!isCancelled && currentGenerator != null
        && !(isStarted = currentGenerator.startNext())) {
      stage = getNextStage(stage);
      currentGenerator = getNextGenerator();

      if (stage == Stage.SOURCE) {
        reschedule();
        return;
      }
    }
   
    if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
      notifyFailed();
    }

  }
}

在DecodeJob被構(gòu)造和初始化時毯侦,RunReason設(shè)置為INITIALIZE哭靖,也就是說,runWrapped進入了INITIALIZE這個case侈离,如代碼所示试幽,有處理過的緩存資源加載器、原始圖片資源緩存加載器和遠程圖片資源加載器3種不同類型的加載器卦碾,會根據(jù)當前的狀態(tài)決定使用哪一個铺坞,由于是首次加載,因此洲胖,將獲取到遠程圖片資源加載器济榨,即SourceGenerator這個對象。

runGenerators方法內(nèi)是一個while遞歸循環(huán)绿映,它通過加載器的startNext方法來執(zhí)行加載的任務(wù)擒滑,開啟成功結(jié)束循環(huán),不再尋找新的加載器叉弦。

class SourceGenerator implements DataFetcherGenerator,
    DataFetcher.DataCallback<Object>,
    DataFetcherGenerator.FetcherReadyCallback {

  private final DecodeHelper<?> helper;

  private volatile ModelLoader.LoadData<?> loadData;

  public boolean startNext() {
    //判斷是否有緩存
    if (dataToCache != null) {
      Object data = dataToCache;
      dataToCache = null;
      // 緩存數(shù)據(jù)
      cacheData(data);
    }

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

    // 沒有緩存丐一,從遠程加載
    loadData = null;
    boolean started = false;
     // 遍歷所有的ModelLoader模塊加載器
    while (!started && hasNextModelLoader()) {
      //拿到 HttpGlideUrlLoader 對象
      loadData = helper.getLoadData().get(loadDataListIndex++);
      if (loadData != null
          && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
          || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
        started = true;
        // 調(diào)用 HttpUrlFetcher 的 loadData 方法
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }
    return started;
  }

}

DecodeHelper是在Engine中構(gòu)建的,使用getLoadData獲取到ModelLoader的列表淹冰。

final class DecodeHelper<Transcode> {

    //獲取List<LoadData<?>>
   List<LoadData<?>> getLoadData() {
    if (!isLoadDataSet) {
      isLoadDataSet = true;
      loadData.clear();
      List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
      
      for (int i = 0, size = modelLoaders.size(); i < size; i++) {
        //這個ModelLoader為HttpGlideUrlLoader
        ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
        //構(gòu)建LoadData
        LoadData<?> current =
            modelLoader.buildLoadData(model, width, height, options);
        if (current != null) {
          loadData.add(current);
        }
      }
    }
    return loadData;
  }
}

這里獲取到ModelLoader為HttpGlideUrlLoader類型的库车,通過buildLoadData構(gòu)建一個ModelLoader.LoadData對象。

public class HttpGlideUrlLoader implements ModelLoader<GlideUrl, InputStream> {


   public LoadData<InputStream> buildLoadData(@NonNull GlideUrl model, int width, int height,
      @NonNull Options options) {
     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);
    //構(gòu)建HttpUrlFetcher將它傳遞給LoadData
    return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
   }
}

因此榄棵,上面loadData.fetcher.loadData代碼就是在HttpUrlFetcher中執(zhí)行的凝颇。

public class HttpUrlFetcher implements DataFetcher<InputStream> {
    
  @Override
  public void loadData(@NonNull Priority priority,
      @NonNull DataCallback<? super InputStream> callback) {
    long startTime = LogTime.getLogTime();

    // 調(diào)用 loadDataWithRedirects 方法執(zhí)行網(wǎng)絡(luò)請求
    try {
      InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
      //將輸入流回調(diào)給DataCallback
      callback.onDataReady(result);
    } catch (IOException e) {
      if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "Failed to load data for url", e);
      }
      callback.onLoadFailed(e);
    } finally {
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));
      }
    }
  }

  //執(zhí)行網(wǎng)絡(luò)請求
  private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,
      Map<String, String> headers) throws IOException {

    if (redirects >= MAXIMUM_REDIRECTS) {
      throw new HttpException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
    } else {
     try {
        if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
          throw new HttpException("In re-direct loop");
        }
      } catch (URISyntaxException e) {
        
      }
    }
    //根據(jù)url構(gòu)建Connection 
    urlConnection = connectionFactory.build(url);
    for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
      urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
    }
    urlConnection.setConnectTimeout(timeout);
    urlConnection.setReadTimeout(timeout);
    urlConnection.setUseCaches(false);
    urlConnection.setDoInput(true);

    urlConnection.setInstanceFollowRedirects(false);

    //請求下載
    urlConnection.connect();
   
    //先將輸入流保存
    stream = urlConnection.getInputStream();
    //如果沒有突然被取消
    if (isCancelled) {
      return null;
    }
    //狀態(tài)碼
    final int statusCode = urlConnection.getResponseCode();
    //狀態(tài)碼為200潘拱,將輸入流返回
    if (isHttpOk(statusCode)) {
      return getStreamForSuccessfulRequest(urlConnection);
    } else if (isHttpRedirect(statusCode)) {
      String redirectUrlString = urlConnection.getHeaderField("Location");
      if (TextUtils.isEmpty(redirectUrlString)) {
        throw new HttpException("Received empty or null redirect url");
      }
      URL redirectUrl = new URL(url, redirectUrlString);
      
      cleanup();
      return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
    } else if (statusCode == INVALID_STATUS_CODE) {
      throw new HttpException(statusCode);
    } else {
      throw new HttpException(urlConnection.getResponseMessage(), statusCode);
    }
  }

  //獲取輸入流
   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;
  }

  //狀態(tài)碼為200
  private static boolean isHttpOk(int statusCode) {
    return statusCode / 100 == 2;
  }
}

分析到這疹鳄,總算看到網(wǎng)絡(luò)請求的調(diào)用了。如果狀態(tài)為200芦岂,那么將獲取得數(shù)據(jù)輸入流瘪弓,回調(diào)給DataCallback接口,它是從loadData方法傳遞進來的禽最,再回頭loadData的調(diào)用知道腺怯,它其實就是SourceGenerator對象。


class SourceGenerator implements DataFetcherGenerator,
    DataFetcher.DataCallback<Object>,
    DataFetcherGenerator.FetcherReadyCallback {

   private final FetcherReadyCallback cb;
   private final DecodeHelper<?> helper;
    //緩存流
    private Object dataToCache;
  SourceGenerator(DecodeHelper<?> helper, FetcherReadyCallback cb) {
    this.helper = helper;
    this.cb = cb;
  }

    @Override
  public void onDataReady(Object data) {
    DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
    //如果設(shè)置了磁盤緩存
    if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
      //將數(shù)據(jù)流緩存到磁盤對象中
      dataToCache = data;
      // 重啟 DecodeJob 任務(wù)
       cb.reschedule();
    } else {
      //沒有緩存川无,回調(diào)給DecodeJob
      cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,
          loadData.fetcher.getDataSource(), originalKey);
    }
  }

}

Glide認為遠程網(wǎng)絡(luò)圖片獲取是昂貴的呛占,所以默認情況下網(wǎng)絡(luò)圖片會緩存原圖,但本地圖片懦趋,包括drawable/assets等不會緩存原圖晾虑。

有沒有緩存,最終都會調(diào)用到onDataFetcherReady這個方法。與沒有緩存相比帜篇,有緩存流程上的區(qū)別是糙捺,會將數(shù)據(jù)流緩存到磁盤中,然后開一個新的線程笙隙,再通過另一個緩存加載器處理洪灯,并獲取數(shù)據(jù)流。以上說過竟痰,默認是有緩存原圖的签钩,因此,我們先分析緩存的調(diào)用流程坏快。

在這里提一下边臼,整個流程的調(diào)用就類似一個命令下發(fā),這個命令會一層層往下傳遞假消,傳給到最后一棒的對象去取得數(shù)據(jù)柠并,再沿著原來的路線,將完成的數(shù)據(jù)富拗,一層層往回傳臼予。這一點務(wù)必記住,后面的流程都是在一邊處理數(shù)據(jù)啃沪,一邊向之前的對象傳遞粘拾,直至傳給SingleRequest這個對象里的Target成員,來顯示圖片创千。

因此缰雇,這里就開始了往前的傳遞,調(diào)用reschedule的對象為DecodeJob追驴。

class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
    Runnable,
    Comparable<DecodeJob<?>>,
    Poolable {

 @Override
  public void reschedule() {
    //RunReason被置為SWITCH_TO_SOURCE_SERVICE
    runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
    //回調(diào)給EngineJob
    callback.reschedule(this);
  }

RunReason被置為SWITCH_TO_SOURCE_SERVICE械哟。緊接著再次往回通知EngineJob對象。

class EngineJob<R> implements DecodeJob.Callback<R>,
    Poolable {

  @Override
  public void reschedule(DecodeJob<?> job) {
        getActiveSourceExecutor().execute(job);
  }
}

重新開啟線程殿雪,執(zhí)行DecodeJob這個任務(wù)暇咆。這回直接執(zhí)行runGenerators方法,再次調(diào)用SourceGenerator的startNext方法丙曙,此時緩存就不為null了爸业。

class SourceGenerator implements DataFetcherGenerator,
    DataFetcher.DataCallback<Object>,
    DataFetcherGenerator.FetcherReadyCallback {
  //緩存流
  private Object dataToCache;
  //緩存加載器
  private DataCacheGenerator sourceCacheGenerator;

  @Override
  public boolean startNext() {
    //緩存不為null
    if (dataToCache != null) {
      Object data = dataToCache;
      dataToCache = null;
      cacheData(data);
    }
  //此時sourceCacheGenerator 不為null
  if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
      return true;
    }
   ......
  }

  private void cacheData(Object dataToCache) {
    long startTime = LogTime.getLogTime();
    try {
      Encoder<Object> encoder = helper.getSourceEncoder(dataToCache);
      DataCacheWriter<Object> writer =
          new DataCacheWriter<>(encoder, dataToCache, helper.getOptions());
      originalKey = new DataCacheKey(loadData.sourceKey, helper.getSignature());
      helper.getDiskCache().put(originalKey, writer);
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Finished encoding source to cache"
            + ", key: " + originalKey
            + ", data: " + dataToCache
            + ", encoder: " + encoder
            + ", duration: " + LogTime.getElapsedMillis(startTime));
      }
    } finally {
      loadData.fetcher.cleanup();
    }

    //構(gòu)建緩存加載器來處理
    sourceCacheGenerator =
        new DataCacheGenerator(Collections.singletonList(loadData.sourceKey), helper, this);
  }

dataToCache 將不再是 null ,所以會將數(shù)據(jù)緩存到本地硬盤亏镰,并啟動另一個加載器DataCacheGenerator扯旷,這個加載器正是用來加載緩存在本地的圖片的。它賦值給了成員變量sourceCacheGenerator 索抓,隨后執(zhí)行其startNext方法钧忽。

DataCacheGenerator和ResourceCacheGenerator這兩個加載器跟SourceGenerator類似某抓,只不過根據(jù)不同情形的圖片進行加載:

  • DataCacheGenerator:用于加載原始圖片。
  • ResourceCacheGenerator:用于加載處理過的圖片惰瓜。
  • SourceGenerator:用于加載網(wǎng)絡(luò)圖片否副。

因此,數(shù)據(jù)從緩存中加載成功崎坊,同樣回傳給DataCacheGenerator的 onDataReady方法备禀。

class DataCacheGenerator implements DataFetcherGenerator,
    DataFetcher.DataCallback<Object> {

   public void onDataReady(Object data) {
    cb.onDataFetcherReady(sourceKey, data, loadData.fetcher, DataSource.DATA_DISK_CACHE, sourceKey);
  }
}

前面我們提到過,有沒有緩存奈揍,最終都會調(diào)用DecodeJob的onDataFetcherReady方法曲尸,因為它是用來解碼的。

class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
    Runnable,
    Comparable<DecodeJob<?>>,
    Poolable {

   @Override
   public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,
      DataSource dataSource, Key attemptedKey) {
    this.currentSourceKey = sourceKey;
    this.currentData = data;
    this.currentFetcher = fetcher;
    this.currentDataSource = dataSource;
    this.currentAttemptingKey = attemptedKey;
    
    if (Thread.currentThread() != currentThread) {
      runReason = RunReason.DECODE_DATA;
      callback.reschedule(this);
    } else {
      GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
      try {
        //解碼數(shù)據(jù)
        decodeFromRetrievedData();
      } finally {
        GlideTrace.endSection();
      }
    }

  //解碼獲取Resource
   private void decodeFromRetrievedData() {
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
      logWithTimeAndKey("Retrieved data", startFetchTime,
          "data: " + currentData
              + ", cache key: " + currentSourceKey
              + ", fetcher: " + currentFetcher);
    }
    Resource<R> resource = null;
    try {
      //解碼得到LazyBitmapDrawableResource
      resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    } catch (GlideException e) {
      e.setLoggingDetails(currentAttemptingKey, currentDataSource);
      throwables.add(e);
    }

    //進行編碼輸出
    if (resource != null) {
      notifyEncodeAndRelease(resource, currentDataSource);
    } else {
      runGenerators();
    }
  }

  private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data,
      DataSource dataSource) throws GlideException {
    try {
      if (data == null) {
        return null;
      }
      long startTime = LogTime.getLogTime();
      //從DecodeHelper中獲取LoadPath對象
      Resource<R> result = decodeFromFetcher(data, dataSource);
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        logWithTimeAndKey("Decoded result " + result, startTime);
      }
      return result;
    } finally {
      fetcher.cleanup();
    }
  }

  private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
      throws GlideException {
    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);
    DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
    try {
      //使用LoadPath進行解碼
      return path.load(
          rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
    } finally {
      rewinder.cleanup();
    }
  }
}

解碼的流程最終是通過LoadPath這個對象來進行處理的男翰。它是根據(jù)傳入的處理數(shù)據(jù)另患,來返回特定的數(shù)據(jù)解碼處理器對象。

public class LoadPath<Data, ResourceType, Transcode> {
  

  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 {
        //開始解碼
        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類還并不是最終的解碼器蛾绎,它只是封裝解碼和轉(zhuǎn)碼的工具昆箕,它本身不做解碼轉(zhuǎn)碼的具體操作。

public class DecodePath<DataType, ResourceType, Transcode> {
  //轉(zhuǎn)碼器
  private final ResourceTranscoder<ResourceType, Transcode> transcoder;

  public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
      @NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
     // 返回的可能是 BitmapResource 對象租冠,看具體類型
    Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);

    // 回調(diào) DecodeJob 的 onResourceDecoded 方法鹏倘,返回需要轉(zhuǎn)碼的類型
    Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);

    //轉(zhuǎn)碼 BitmapResource,返回 LazyBitmapDrawableResource
    return transcoder.transcode(transformed, options);
  }

  private Resource<ResourceType> decodeResourceWithList(DataRewinder<DataType> rewinder, int width,
      int height, @NonNull Options options, List<Throwable> exceptions) throws GlideException {

    Resource<ResourceType> result = null;

   //遍歷獲取StreamBitmapDecoder
    for (int i = 0, size = decoders.size(); i < size; i++) {
      ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);
      try {
        DataType data = rewinder.rewindAndGet();
        if (decoder.handles(data, options)) {
          data = rewinder.rewindAndGet();
          //解碼成Drawable 
          result = decoder.decode(data, width, height, options);
        }
       
      } catch (IOException | RuntimeException | OutOfMemoryError e) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
          Log.v(TAG, "Failed to decode data for " + decoder, e);
        }
        exceptions.add(e);
      }

      if (result != null) {
        break;
      }
    }

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

}

這里需要的是 Drawable 類型顽爹,所以纤泵,decodeResource方法最終會通過 StreamBitmapDecoder將數(shù)據(jù)流解碼成一個 BitmapResource 對象。再通過ResourceTranscoder轉(zhuǎn)碼器镜粤,它是BitmapDrawableTranscoder類型的捏题,轉(zhuǎn)碼為LazyBitmapDrawableResource對象。

public class BitmapDrawableTranscoder implements ResourceTranscoder<Bitmap, BitmapDrawable> {
  private final Resources resources;

  @SuppressWarnings("unused")
  public BitmapDrawableTranscoder(@NonNull Context context) {
    this(context.getResources());
  }
 
  @Deprecated
  public BitmapDrawableTranscoder(
      @NonNull Resources resources, @SuppressWarnings("unused") BitmapPool bitmapPool) {
    this(resources);
  }

  public BitmapDrawableTranscoder(@NonNull Resources resources) {
    this.resources = Preconditions.checkNotNull(resources);
  }

  //轉(zhuǎn)碼
  @Override
  public Resource<BitmapDrawable> transcode(@NonNull Resource<Bitmap> toTranscode,
      @NonNull Options options) {
    return LazyBitmapDrawableResource.obtain(resources, toTranscode);
  }
}
public final class LazyBitmapDrawableResource implements Resource<BitmapDrawable>,
    Initializable {

  //獲取LazyBitmapDrawableResource對象
  public static Resource<BitmapDrawable> obtain(
      @NonNull Resources resources, @Nullable Resource<Bitmap> bitmapResource) {
    if (bitmapResource == null) {
      return null;
    }
    return new LazyBitmapDrawableResource(resources, bitmapResource);

  }

  //獲取BitmapDrawable
  @Override
  public BitmapDrawable get() {
    return new BitmapDrawable(resources, bitmapResource.get());
  }

}

這里注意到get方法返回了BitmapDrawable對象肉渴,它就是最終用來顯示到ImageView上的類型」現(xiàn)在解碼和轉(zhuǎn)碼工作已經(jīng)完成了。所以黄虱,數(shù)據(jù)繼續(xù)往回傳遞通知上層稚矿,將獲取到的結(jié)果進行展示。

因此捻浦,回到DecodeJob類的decodeFromRetrievedData方法內(nèi)部,調(diào)用notifyEncodeAndRelease 繼續(xù)往下執(zhí)行桥爽。

class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
    Runnable,
    Comparable<DecodeJob<?>>,
    Poolable {

  private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
    if (resource instanceof Initializable) {
      ((Initializable) resource).initialize();
    }
    //將資源鎖定
    Resource<R> result = resource;
    LockedResource<R> lockedResource = null;
    if (deferredEncodeManager.hasResourceToEncode()) {
      lockedResource = LockedResource.obtain(resource);
      result = lockedResource;
    }
    //通知上層任務(wù)完成
    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<R> resource, DataSource dataSource) {
    setNotifiedOrThrow();
    //回調(diào)給EngineJob
    callback.onResourceReady(resource, dataSource);
  }

}

LazyBitmapDrawableResource數(shù)據(jù)繼續(xù)往回傳給EngineJob類朱灿。它還會繼續(xù)往上傳給SingleRequest類。

class EngineJob<R> implements DecodeJob.Callback<R>,
    Poolable {
//這是LazyBitmapDrawableResource
 private Resource<?> resource;

  @Override
  public void onResourceReady(Resource<R> resource, DataSource dataSource) {
    //保存數(shù)據(jù)
    synchronized (this) {
      this.resource = resource;
      this.dataSource = dataSource;
    }
    notifyCallbacksOfResult();
  }

  @Synthetic
  void notifyCallbacksOfResult() {

    ResourceCallbacksAndExecutors copy;
    Key localKey;
    EngineResource<?> localResource;
    synchronized (this) {
      stateVerifier.throwIfRecycled();
      if (isCancelled) {
        resource.recycle();
        release();
        return;
      } else if (cbs.isEmpty()) {
        throw new IllegalStateException("Received a resource without any callbacks to notify");
      } else if (hasResource) {
        throw new IllegalStateException("Already have resource");
      }
    //構(gòu)建EngineResource
      engineResource = engineResourceFactory.build(resource, isCacheable);
      
      hasResource = true;
      copy = cbs.copy();
      incrementPendingCallbacks(copy.size() + 1);
      localKey = key;
      localResource = engineResource;
    }

    listener.onEngineJobComplete(this, localKey, localResource);
    //通過子線程回調(diào)
    for (final ResourceCallbackAndExecutor entry : copy) {
      entry.executor.execute(new CallResourceReady(entry.cb));
    }
    decrementPendingCallbacks();
  }


   private class CallResourceReady implements Runnable {

    private final ResourceCallback cb;

    CallResourceReady(ResourceCallback cb) {
      this.cb = cb;
    }

    @Override
    public void run() {
      synchronized (EngineJob.this) {
        if (cbs.contains(cb)) {
       
          engineResource.acquire();
          //調(diào)用callCallbackOnResourceReady傳遞給SingleRequest
          callCallbackOnResourceReady(cb);
          removeCallback(cb);
        }
        decrementPendingCallbacks();
      }
    }
  }

  @SuppressWarnings("WeakerAccess")
  @Synthetic
  synchronized void callCallbackOnResourceReady(ResourceCallback cb) {
    try {
      //調(diào)用SingleRequest的onResourceReady方法
      cb.onResourceReady(engineResource, dataSource);
    } catch (Throwable t) {
      throw new CallbackException(t);
    }
  }

}

EngineJob構(gòu)建了一個EngineResource钠四,將LazyBitmapDrawableResource封裝在它的內(nèi)部盗扒,然后開啟線程跪楞,將數(shù)據(jù)傳遞給了SingleRequest類。

public final class SingleRequest<R> implements Request,
    SizeReadyCallback,
    ResourceCallback,
    FactoryPools.Poolable {
  
     @Override
  public synchronized void onResourceReady(Resource<?> resource, DataSource dataSource) {
    stateVerifier.throwIfRecycled();
    loadStatus = null;
    if (resource == null) {
      GlideException exception = new GlideException("Expected to receive a Resource<R> with an "
          + "object of " + transcodeClass + " inside, but instead got null.");
      onLoadFailed(exception);
      return;
    }
    從EngineResource中獲取BitmapDrawable對象
    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);
      status = Status.COMPLETE;
      return;
    }
  //通知Target顯示圖片
    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;
      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.onResourceReady(result, animation);
      }
    } finally {
      isCallingCallbacks = false;
    }

    notifyLoadSuccess();
  }
}

注意代碼中的resource.get()調(diào)用侣灶,這個resource是傳遞過來的EngineResource甸祭,上面說過,它已經(jīng)持有了LazyBitmapDrawableResource褥影,這個get方法池户,便會調(diào)用LazyBitmapDrawableResource的get方法獲取到BitmapDrawable對象,緊接著調(diào)用onResourceReady方法讓Target去展示圖片凡怎。

在最前面分析說過校焦,這個Target是ImageViewTarget的子類,BitmapImageViewTarget统倒。

public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z>
    implements Transition.ViewAdapter {
  
   @Override
  public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
    if (transition == null || !transition.transition(resource, this)) {
      //設(shè)置資源
      setResourceInternal(resource);
    } else {
      maybeUpdateAnimatable(resource);
    }
  }

    private void setResourceInternal(@Nullable Z resource) {
    //調(diào)用子類方法
    setResource(resource);
    maybeUpdateAnimatable(resource);
  }
  
   protected abstract void setResource(@Nullable Z resource);
}
public class DrawableImageViewTarget extends ImageViewTarget<Drawable> {

  public DrawableImageViewTarget(ImageView view) {
    super(view);
  }

  @SuppressWarnings({"unused", "deprecation"})
  @Deprecated
  public DrawableImageViewTarget(ImageView view, boolean waitForLayout) {
    super(view, waitForLayout);
  }

  //顯示圖片
  @Override
  protected void setResource(@Nullable Drawable resource) {
    view.setImageDrawable(resource);
  }
}

到此寨典,Glide整個圖片加載流程分析完畢。其中的into流程是最復雜的房匆,因為Glide做了大量的緩存處理和對象復用耸成。但整個基本調(diào)用流程是:下發(fā)一個Request后,通過網(wǎng)絡(luò)請求獲得數(shù)據(jù)浴鸿,進行解碼和轉(zhuǎn)碼墓猎,再沿路返回到Request類中,讓Target去做圖片展示赚楚。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末毙沾,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子宠页,更是在濱河造成了極大的恐慌左胞,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件举户,死亡現(xiàn)場離奇詭異烤宙,居然都是意外死亡,警方通過查閱死者的電腦和手機俭嘁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門躺枕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人供填,你說我怎么就攤上這事拐云。” “怎么了近她?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵叉瘩,是天一觀的道長。 經(jīng)常有香客問我粘捎,道長薇缅,這世上最難降的妖魔是什么危彩? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮泳桦,結(jié)果婚禮上汤徽,老公的妹妹穿的比我還像新娘。我一直安慰自己灸撰,他們只是感情好谒府,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著梧奢,像睡著了一般狱掂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上亲轨,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天趋惨,我揣著相機與錄音,去河邊找鬼惦蚊。 笑死器虾,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的蹦锋。 我是一名探鬼主播兆沙,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼莉掂!你這毒婦竟也來了葛圃?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤憎妙,失蹤者是張志新(化名)和其女友劉穎库正,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體厘唾,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡褥符,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了抚垃。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喷楣。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鹤树,靈堂內(nèi)的尸體忽然破棺而出铣焊,到底是詐尸還是另有隱情,我是刑警寧澤魂迄,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布粗截,位于F島的核電站,受9級特大地震影響捣炬,放射性物質(zhì)發(fā)生泄漏熊昌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一湿酸、第九天 我趴在偏房一處隱蔽的房頂上張望婿屹。 院中可真熱鬧,春花似錦推溃、人聲如沸昂利。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蜂奸。三九已至,卻和暖如春硬萍,著一層夾襖步出監(jiān)牢的瞬間扩所,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工朴乖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留祖屏,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓买羞,卻偏偏與公主長得像袁勺,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子畜普,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348