Android 架构之Glide源码解读(中)①

前言

在上一篇中,主要讲解了Glide 基础知识点以及with、load、into这三部曲中的with,知道了在with中Glide主要帮我们做了生命周期相互绑定的相关工作。在这一篇中,将会对load、into进一步解读相应的源码。
Android开发Glide原理解析/面试题解析_哔哩哔哩_bilibili
本篇解读的源码版本:4.11.0,读者也可以根据本章步骤,在AS中一步一步解读源码。

1、load 方法

  @NonNull
  @CheckResult
  @Override
  public RequestBuilder load(@Nullable String string) {
    return asDrawable().load(string);
  }

源码解析

这里有两个方法 asDrawableload 现在分别进行源码解读。

1.1 asDrawable 方法

  @NonNull
  @CheckResult
  public RequestBuilder asDrawable() {
    return as(Drawable.class);
  }

源码解析

这里调用了as 方法,继续追进

  @NonNull
  @CheckResult
  public  RequestBuilder as(
      @NonNull Class resourceClass) {
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }

源码解析

到这,我们应该知道 asDrawable 方法最终 返回的是 RequestBuilder 对象,然后调用 load 方法。接下来就该分析 load方法是怎样走的。

1.2 load 方法

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

源码解析

这里调用了 loadGeneric 方法继续追进。

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

源码解析

从这可以看出,loadGeneric 将对应参数(图片地址) 赋值给当前类的全局变量,最后再将该类返回。

1.3 图解总结

这里虽然简单,但还是用一张图来总结一下,load的整个流程。

2、into 方法

温馨提示:这里过程有点长,因为几乎所有的Glide逻辑都在这个方法里面。建议收藏关注一波,确保在足够多的空闲时间时再来捋一遍。

 @NonNull
  public ViewTarget into(@NonNull ImageView view) {
    Util.assertMainThread();
    ...略
    return into(
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions,
        Executors.mainThreadExecutor());
  }

源码解析

这里首先进行了是否为主线程的处理,其次调用了 into 方法,进去看看。

  private > Y into(
      @NonNull Y target,
      @Nullable RequestListener targetListener,
      BaseRequestOptions options,
      Executor callbackExecutor) {

    //构建 Request  对象
    Request request = buildRequest(target, targetListener, options, callbackExecutor);

    Request previous = target.getRequest();
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
      //这里是 请求失败重试判断,看是否重试
      if (!Preconditions.checkNotNull(previous).isRunning()) {
        previous.begin();
      }
      return target;
    }
    //这里是正常请求
    requestManager.clear(target);
    target.setRequest(request);
    requestManager.track(target, request);
    return target;
  }

源码解析

这里 先是进行了 Request 对象的构建,其次进行了 当前 Request 是否是新请求以及是否要重试,最后通过 requestManager.track 进行网络请求。先来分析一下 Request 对象的构建,进入buildRequest 方法。

2.1 开启 buildRequest 支线

  private Request buildRequest(
      Target target,
      @Nullable RequestListener targetListener,
      BaseRequestOptions requestOptions,
      Executor callbackExecutor) {
    return buildRequestRecursive(
        /*requestLock=*/ new Object(),
        target,
        targetListener,
        /*parentCoordinator=*/ null,
        transitionOptions,
        requestOptions.getPriority(),
        requestOptions.getOverrideWidth(),
        requestOptions.getOverrideHeight(),
        requestOptions,
        callbackExecutor);
  }

源码解析

这里直接调用了 buildRequestRecursive 方法,进去看看。

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

    ...略

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

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

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

    Request errorRequest =
        errorBuilder.buildRequestRecursive(
            requestLock,
            target,
            targetListener,
            errorRequestCoordinator,
            errorBuilder.transitionOptions,
            errorBuilder.getPriority(),
            errorOverrideWidth,
            errorOverrideHeight,
            errorBuilder,
            callbackExecutor);
    errorRequestCoordinator.setRequests(mainRequest, errorRequest);
    return errorRequestCoordinator;
  }

源码解析

从这里可以看出,先是通过 buildThumbnailRequestRecursive 方法构建了 mainRequest 变量 ,如果没有失败请求(重试),那就直接返回。下面的也是处理因为失败的重试请求,最终也是返回了 Request 类型的变量。我们就不看重试的,直接进入 buildThumbnailRequestRecursive 方法。


  private Request buildThumbnailRequestRecursive(
      Object requestLock,
      Target target,
      RequestListener targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      BaseRequestOptions requestOptions,
      Executor callbackExecutor) {
      ...略
      Request fullRequest =
          obtainRequest(
              requestLock,
              target,
              targetListener,
              requestOptions,
              coordinator,
              transitionOptions,
              priority,
              overrideWidth,
              overrideHeight,
              callbackExecutor);
      isThumbnailBuilt = true;
      // Recursively generate thumbnail requests.
      Request thumbRequest =
          thumbnailBuilder.buildRequestRecursive(
              requestLock,
              target,
              targetListener,
              coordinator,
              thumbTransitionOptions,
              thumbPriority,
              thumbOverrideWidth,
              thumbOverrideHeight,
              thumbnailBuilder,
              callbackExecutor);
      isThumbnailBuilt = false;
      coordinator.setRequests(fullRequest, thumbRequest);
      return coordinator;
    } else if (thumbSizeMultiplier != null) {
      // Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
      ThumbnailRequestCoordinator coordinator =
          new ThumbnailRequestCoordinator(requestLock, parentCoordinator);
      Request fullRequest =
          obtainRequest(
              requestLock,
              target,
              targetListener,
              requestOptions,
              coordinator,
              transitionOptions,
              priority,
              overrideWidth,
              overrideHeight,
              callbackExecutor);
      BaseRequestOptions thumbnailOptions =
          requestOptions.clone().sizeMultiplier(thumbSizeMultiplier);

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

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


源码解析

从这可以看出,这里最多会有俩个请求 一个 fullRequest 正常状态的请求 ,thumbRequest 图标缩略图的请求。而正常请求 fullRequest 又是通过 obtainRequest 方法构建的,进去看看。

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

源码解析

这里调用了 SingleRequest.obtain 方法,继续追进。

  public static  SingleRequest obtain(
      Context context,
      GlideContext glideContext,
      Object requestLock,
      Object model,
      Class transcodeClass,
      BaseRequestOptions requestOptions,
      int overrideWidth,
      int overrideHeight,
      Priority priority,
      Target target,
      RequestListener targetListener,
      @Nullable List> requestListeners,
      RequestCoordinator requestCoordinator,
      Engine engine,
      TransitionFactory animationFactory,
      Executor callbackExecutor) {
    return new SingleRequest<>(
        context,
        glideContext,
        requestLock,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        engine,
        animationFactory,
        callbackExecutor);
  }

源码解析

这个方法返回了 SingleRequest 对象。到这,buildRequest 支线已经走完了。这里的 SingleRequest 对象,将会依次返回到主线,接下来回到主线看看。

2.2 结束 buildRequest 支线,回到主线。

避免来回翻,这里再贴主线代码。

  private > Y into(
      @NonNull Y target,
      @Nullable RequestListener targetListener,
      BaseRequestOptions options,
      Executor callbackExecutor) {

    //构建 Request  对象
    Request request = buildRequest(target, targetListener, options, callbackExecutor);

    Request previous = target.getRequest();
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
      //这里是 请求失败重试判断,看是否重试
      if (!Preconditions.checkNotNull(previous).isRunning()) {
        previous.begin();
      }
      return target;
    }
    //这里是正常请求
    requestManager.clear(target);
    target.setRequest(request);
    requestManager.track(target, request);
    return target;
  }

总结

到这,我们应该能明白 buildRequest 方法返回的 Request 对象,里面阔能会含有 缩略图 请求的封装。现在继续 看 requestManager.track 方法。

2.3 开启 requestManager.track 支线

  synchronized void track(@NonNull Target target, @NonNull Request request) {
    targetTracker.track(target);
    requestTracker.runRequest(request);
  }

源码解析

这里分别调用了 targetTracker.trackrequestTracker.runRequest 方法,依次进去看看。

  • targetTracker.track
  public void track(@NonNull Target target) {
    targets.add(target);
  }

源码解析

这里我们可以理解为 将这个任务添加至某个集合里面。

  • requestTracker.runRequest
  /** Starts tracking the given request. */
  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);
    }
  }

源码解析

这里首先有两个集合,分别为:正在执行队列、暂停后等待执行队列。先是将该请求加入正在执行队列,然后判断当前Glide是否为暂停状态,如果否,则直接运行执行队列,如果是则清空正在执行队列,将当前请求加入等待执行队列。现在我们肯定是看执行的,于是进入begin方法看看。

如图所示

进入SingleRequest 里面的 begin 方法

  @Override
  public void begin() {
    synchronized (requestLock) {
      assertNotCallingCallbacks();
      stateVerifier.throwIfRecycled();
      startTime = LogTime.getLogTime();
      
      ...略

      //如果当前图片已经正在运行了,
      if (status == Status.RUNNING) {
        throw new IllegalArgumentException("Cannot restart a running request");
      }
      
      // 如果当前状态为已完成状态,那么直接返回
      if (status == Status.COMPLETE) {
        onResourceReady(resource, DataSource.MEMORY_CACHE);
        return;
      }

      //设置当前状态为等待状态
      status = Status.WAITING_FOR_SIZE;
      //进行宽高的判断,宽高是否大于0
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
        //满足进入该方法
        onSizeReady(overrideWidth, overrideHeight);
      } else {
        target.getSize(this);
      }

     ...略
    }
  }

源码解析

从这可以看出,这里进行了一系列的逻辑判断,最终会进入 onSizeReady 方法。进入看看。

public final class SingleRequest implements Request, SizeReadyCallback, ResourceCallback {

...略

 @Override
  public void onSizeReady(int width, int height) {
    stateVerifier.throwIfRecycled();
    synchronized (requestLock) {
      if (status != Status.WAITING_FOR_SIZE) {
        return;
      }
      status = Status.RUNNING;
      float sizeMultiplier = requestOptions.getSizeMultiplier();
      this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
      this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
      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, // SingleRequest implements Request, SizeReadyCallback, ResourceCallback
              callbackExecutor);
      if (status != Status.RUNNING) {
        loadStatus = null;
      }
    }
  }

...略
}

源码解析

从这可以看出,如果这里status 不等于上面设置的 等待状态,那么将直接终止。过后将对应的 status 设置为运行状态,随后根据比例进行了 宽高计算,最后调用了 engine.load 方法,并且传入了 当前对象 this ,而当前类实现了 Request, SizeReadyCallback, ResourceCallback 对应的接口,用来响应回调。我们进入engine.load 该方法看看。

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

    //根据对应的请求方式,生成对应请求的缓存key值
    EngineKey key =
        keyFactory.buildKey(
            model,
            signature,
            width,
            height,
            transformations,
            resourceClass,
            transcodeClass,
            options);

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

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

    //如果成功从缓存里面拿到对应数据了,那么调用onResourceReady方法将缓存数据返回给上一层。
    cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
    return null;
  }

源码解析

这里首先根据相应的请求生成了对应的缓存key ,然后调用 loadFromMemory 方法查询是否有对应缓存,如果有则通过 cb.onResourceReady 方法将对应缓存数据返回给上一层;如果没有则调用 waitForExistingOrStartNewJob 方法。

我们先进入 loadFromMemory 方法看看

  @Nullable
  private EngineResource loadFromMemory(
      EngineKey key, boolean isMemoryCacheable, long startTime) {
    //判断是否开启缓存
    if (!isMemoryCacheable) {
      return null;
    }
    //读取活动缓存
    EngineResource active = loadFromActiveResources(key);
    if (active != null) {
      return active;
    }
    //读取内存缓存
    EngineResource cached = loadFromCache(key);
    if (cached != null) {
      return cached;
    }
    return null;
  }

源码解析

从这段代码可以看出,如果没开启缓存,返回null,如果没有活动缓存则读取内存缓存,如果其中一个有缓存则返回对应缓存,如果两个都没有则返回null。

接下来该进入 waitForExistingOrStartNewJob 方法看看。

  private  LoadStatus waitForExistingOrStartNewJob(
      GlideContext glideContext,
      Object model,
      Key signature,
      int width,
      int height,
      Class resourceClass,
      Class transcodeClass,
      Priority priority,
      DiskCacheStrategy diskCacheStrategy,
      Map, Transformation> transformations,
      boolean isTransformationRequired,
      boolean isScaleOnlyOrNoTransform,
      Options options,
      boolean isMemoryCacheable,
      boolean useUnlimitedSourceExecutorPool,
      boolean useAnimationPool,
      boolean onlyRetrieveFromCache,
      ResourceCallback cb, // 具有回调功能
      Executor callbackExecutor,
      EngineKey key,
      long startTime) {
    
    // 从工作队列中通过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);
    }

   //如果没有则根据对应 key 创建对应的工作引擎
    EngineJob engineJob =
        engineJobFactory.build(
            key,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache);

    //创建对应的解码器
    DecodeJob decodeJob =
        decodeJobFactory.build(
            glideContext,
            model,
            key,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            onlyRetrieveFromCache,
            options,
            engineJob);

    //将对应的工作引擎 添加至map中
    jobs.put(key, engineJob);

    //向对应的工作引擎添加可回调的功能
    engineJob.addCallback(cb, callbackExecutor);

    //开始工作,调用解码器
    engineJob.start(decodeJob);

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

接下一篇:Android 架构之Glide源码解读(中)②

你可能感兴趣的:(Android 架构之Glide源码解读(中)①)