> 文档中心 > Glide源码(4.11.0)主线流程梳理(二)---load&into方法的内部逻辑

Glide源码(4.11.0)主线流程梳理(二)---load&into方法的内部逻辑


load 源码梳理

根据上篇文章对with方法的梳理可以知道,Glide.with(this) 返回的是RequestManager对象,所以load方法在RequestManager类里面,现在我们分析一下load方法

public class RequestManager    implements ComponentCallbacks2, LifecycleListener, ModelTypes<RequestBuilder<Drawable>> {  @NonNull  @CheckResult  public RequestBuilder<Drawable> asDrawable() {    return as(Drawable.class);  }  @NonNull  @CheckResult  @Override  public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {    return asDrawable().load(bitmap);  }  @NonNull  @CheckResult  @Override  public RequestBuilder<Drawable> load(@Nullable Drawable drawable) {    return asDrawable().load(drawable);  }  @NonNull  @CheckResult  @Override  public RequestBuilder<Drawable> load(@Nullable String string) {    return asDrawable().load(string);  }// ...  @NonNull  @CheckResult  public <ResourceType> RequestBuilder<ResourceType> as(@NonNull Class<ResourceType> resourceClass) {    return new RequestBuilder<>(glide, this, resourceClass, context);  }  }

从上面的代码可见,asDrawable()方法的主要作用就是构建RequestBuilder;
代码拆开来看,

// 伪代码public RequestBuilder<Drawable> load(@Nullable String string) {    RequestBuilder requestBuilder = asDrawable();requestBuilder = requestBuilder.load(string);    return requestBuilder;  }

下面进入RequestBuilder类,看一下RequestBuilder.load(string)方法;

public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>    implements Cloneable, ModelTypes<RequestBuilder<TranscodeType>> {      public RequestBuilder<TranscodeType> load(@RawRes @DrawableRes @Nullable Integer resourceId) {    return loadGeneric(resourceId).apply(signatureOf(AndroidResourceSignature.obtain(context)));  }  @NonNull  private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {    this.model = model;// 相当于传递过来的资源url    isModelSet = true;// 标记已经加载过资源    return this;// 返回RequestBuilder  }//这个主要是调用父类的方法,初始化 配置信息  @Override  public RequestBuilder<TranscodeType> apply(@NonNull BaseRequestOptions<?> requestOptions) {    Preconditions.checkNotNull(requestOptions);    return super.apply(requestOptions);  }}

至此,load方法的主线流程就差不多完事了,主要就是构建RequestBuilder,为了下一步into做准备

into() 源码梳理

这里才算是真正进入Glide源码的核心之处
由于load方法返回的是RequestBuilder,所以 into方法肯定是在RequestBuilder类里面

RequestBuilder.java

  @NonNull  public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {    Util.assertMainThread();// 主线程检查    Preconditions.checkNotNull(view);// 目标控件  空检查//根据布局文件里面scaleType属性的设置,重置RequestOptions    BaseRequestOptions<?> requestOptions = this;    if (!requestOptions.isTransformationSet() && requestOptions.isTransformationAllowed() && view.getScaleType() != null) {      // Clone in this method so that if we use this RequestBuilder to load into a View and then      // into a different target, we don't retain the transformation applied based on the previous      // View's scale type.      switch (view.getScaleType()) { case CENTER_CROP:   requestOptions = requestOptions.clone().optionalCenterCrop();   break; case CENTER_INSIDE:   requestOptions = requestOptions.clone().optionalCenterInside();   break; case FIT_CENTER: case FIT_START: case FIT_END:   requestOptions = requestOptions.clone().optionalFitCenter();   break; case FIT_XY:   requestOptions = requestOptions.clone().optionalCenterInside();   break; case CENTER: case MATRIX: default:   // Do nothing.      }    }//调用 into 重载函数,创建一个 ViewTarget    return into(    //调用 buildImageViewTarget 构建一个 ImageView 类型的 Target(Bitmap/Drawable) glideContext.buildImageViewTarget(view, transcodeClass), /*targetListener=*/ null, requestOptions, Executors.mainThreadExecutor());  }

上面代码就两大步:
第一步:先拿到当前 ImageView getScaleType 类型的属性,然后重新 clone 一个进行配置;
第二步:调用 into 重载继续构建;

  • 先来看下into方法的第一个参数 glideContext.buildImageViewTarget 是怎么构建出来 ImageViewTarget 的:
  @NonNull  public <X> ViewTarget<ImageView, X> buildImageViewTarget(      @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {    return imageViewTargetFactory.buildTarget(imageView, transcodeClass);  }
public class ImageViewTargetFactory {  @NonNull  @SuppressWarnings("unchecked")  public <Z> ViewTarget<ImageView, Z> buildTarget(      @NonNull ImageView view, @NonNull Class<Z> clazz) {    if (Bitmap.class.equals(clazz)) {    //如果目标的编码类型属于 Bitmap 那么就创建一个 Bitmap 类型的 ImageViewTarget      return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);    } else if (Drawable.class.isAssignableFrom(clazz)) {    //如果目标的编码类型属于 Drawable 那么就创建一个 Drawable 类型的 ImageViewTarget      return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);    } else {      throw new IllegalArgumentException(   "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");    }  }}

注意:上面 生成Target 的时候注意一下,只要调用了 asBitmap 才会执行生成BitmapImageViewTarget ,所以这里我们关注 Drawable 类型就行了,我们就先简单看看这个 target 内部怎么实现的

public class DrawableImageViewTarget extends ImageViewTarget<Drawable> {  public DrawableImageViewTarget(ImageView view) {    super(view);  }  /** @deprecated Use {@link #waitForLayout()} instead. */  // Public API.  @SuppressWarnings({"unused", "deprecation"})  @Deprecated  public DrawableImageViewTarget(ImageView view, boolean waitForLayout) {    super(view, waitForLayout);  }  @Override  protected void setResource(@Nullable Drawable resource) {    view.setImageDrawable(resource);  }}

这里DrawableImageViewTarget 继承 ImageViewTarget,重写了setResource方法,这里是显示图片到控件上的逻辑,记住这里

  • 继续重载into方法
  private <Y extends Target<TranscodeType>> Y into(      @NonNull Y target,      @Nullable RequestListener<TranscodeType> targetListener,      BaseRequestOptions<?> options,      Executor callbackExecutor) {    Preconditions.checkNotNull(target);    //这里的 isModelSet 是在 load 的时候赋值为 true 的,所以不会抛异常    if (!isModelSet) {      throw new IllegalArgumentException("You must call #load() before calling #into()");    }//为这个 http://xxx.png 生成一个 Glide request 请求    Request request = buildRequest(target, targetListener, options, callbackExecutor);//相当于拿到上一个请求    Request previous = target.getRequest();// 先取Request,    //下面的几行说明是否与上一个请求冲突,一般不用管 直接看下面 else 判断    if (request.isEquivalentTo(previous) && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) { // 意思就是说 如果当前请求跟上一次的请求是同一个,那就释放本次请求,执行上一个请求,      request.recycle();      if (!Preconditions.checkNotNull(previous).isRunning()) { previous.begin();      }      return target;    }//清理掉目标请求管理    requestManager.clear(target);    //重新为目标设置一个 Glide request 请求    target.setRequest(request);    //最后是调用 RequestManager 的 track 来执行目标的 Glide request 请求    requestManager.track(target, request);    return target;  }

以上核心就两个点:

  • 第一点:为 target buildRequest 构建一个 Glide request 请求;
  • 第二点:将构建出来的 Request 交于 RequestManager 来执行

简单的来看下怎么构建的 Request:

  private Request buildRequest(...) {    return buildRequestRecursive(...省略参数);  }  //  .... 一系列的方法调用,最终执行到下面的方法    private Request obtainRequest(...省略参数) {    return SingleRequest.obtain(...省略参数);  }

最终是调用了SingleRequest.obtain方法,得到Request之后,交给RequestManager执行requestManager.track(target, request);

  synchronized void track(@NonNull Target<?> target, @NonNull Request request) {     //添加一个目标任务    targetTracker.track(target);  //执行 Glide request    requestTracker.runRequest(request);  }
  public void runRequest(@NonNull Request request) {    //添加一个请求    requests.add(request);    //是否暂停    if (!isPaused) {      //没有暂停,开始调用 Request begin 执行      request.begin();    } else {      //如果调用了 暂停,清理请求      request.clear();      pendingRequests.add(request);    }  }

继续查看Request的执行begin()方法,
在这里插入图片描述
前面已经备注得到的Request是 SingleRequest,所以,在点击begin方法的时候进入了接口Request里面的begin方法,这时候去找实现类,就应该找 SingleRequest的begin方法;

SingleRequest.java

  @Override  public void begin() {    synchronized (requestLock) {      assertNotCallingCallbacks();      stateVerifier.throwIfRecycled();      startTime = LogTime.getLogTime();      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");      }      if (status == Status.COMPLETE) {//表示资源准备好了 onResourceReady(resource, DataSource.MEMORY_CACHE); return;      }      status = Status.WAITING_FOR_SIZE;      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {      //这里表示大小已经准备好了---去寻找缓存,准备资源 onSizeReady(overrideWidth, overrideHeight);      } else { target.getSize(this);      }      if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)   && canNotifyStatusChanged()) { target.onLoadStarted(getPlaceholderDrawable());      }      if (IS_VERBOSE_LOGGABLE) { logV("finished run method in " + LogTime.getElapsedMillis(startTime));      }    }  }

大小准备好之后 去寻找缓存,准备资源
onSizeReady

  @Override  public void onSizeReady(int width, int height) {    stateVerifier.throwIfRecycled();    synchronized (requestLock) {      // ...       loadStatus = engine.load(...省略参数);// ...    }  }

Engine.java
engine.load

public <R> LoadStatus load(...) {// 拿到 key    EngineKey key = keyFactory.buildKey(...);    EngineResource<?> memoryResource;    synchronized (this) {    // 去内存查找      memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);      if (memoryResource == null) {//内存没有找到,执行一个新的任务 return waitForExistingOrStartNewJob(...);      }    }    cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);    return null;  }  // 执行已经存在的任务 或者 开启一个新任务  private <R> LoadStatus waitForExistingOrStartNewJob(...) {    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<R> engineJob = engineJobFactory.build(...);    DecodeJob<R> decodeJob = decodeJobFactory.build(...);    //把当前需要执行的 key 添加进缓存    jobs.put(key, engineJob);//执行任务的回调    engineJob.addCallback(cb, callbackExecutor);    //开始执行。    engineJob.start(decodeJob);    // ...    return new LoadStatus(cb, engineJob);  }

查找内存的过程

  @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;    }    // 活动缓存、内存缓存都没有,就返回null    return null;  }  // 查找内存缓存 private EngineResource<?> loadFromCache(Key key) {    EngineResource<?> cached = getEngineResourceFromCache(key);    if (cached != null) {      cached.acquire();      // 如果内存缓存找到了,就放到活动缓存里面去      //此处注意,是剪切,意思就是 内存缓存和活动缓存只能有一处,不能共存,      // 详情请继续查看activate方法      activeResources.activate(key, cached);    }    return cached;  }

通过 engine.load 这个函数里面的逻辑,同学们我们可以总结3点:

  1. 先构建请求或者缓存 KEY ;

  2. 根据 KEY 从内存缓存中查找对应的资源数据(ActiveResources(活动缓存,内部是一个 Map 用弱引用持有),LruResourceCache),如果有就回调 对应监听的 onResourceReady 表示数据准备好了。

  3. 从执行缓存中查找对应 key 的任务

    1. 如果找到了,就说明已经正在执行了,不用重复执行。

    2. 没有找到,通过 EngineJob.start 开启一个新的请求任务执行。

下面我们就来看下 engineJob.start 具体执行逻辑:
engineJob.start(decodeJob);

  public synchronized void start(DecodeJob<R> decodeJob) {    this.decodeJob = decodeJob;    // 从线程池里得到线程    GlideExecutor executor = decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor(); //开始执行    executor.execute(decodeJob);  }

通过 DecodeJob 源码得知,它是实现的 Runnable 接口,这里 GlideExecutor 线程池开始执行,就会启动 DecodeJob 的 run 函数,我们跟踪 run 的实现:

class DecodeJob<R> implements Runnable ...{  @Override  public void run() {    // ...      if (isCancelled) { notifyFailed(); return;      }      // 开始执行      runWrapped();      // ...     }}
 private void runWrapped() {    switch (runReason) {      case INITIALIZE: //获取资源状态 stage = getNextStage(Stage.INITIALIZE); //根据当前资源状态,获取资源执行器 currentGenerator = getNextGenerator(); //执行 runGenerators(); break;      ...    }  }  private Stage getNextStage(Stage current) {    switch (current) {      case INITIALIZE: //如果外部调用配置了资源缓存策略,那么返回 Stage.RESOURCE_CACHE//否则继续调用 Stage.RESOURCE_CACHE 执行。 return diskCacheStrategy.decodeCachedResource()     ? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);      case RESOURCE_CACHE: //如果外部配置了源数据缓存,那么返回 Stage.DATA_CACHE //否则继续调用 getNextStage(Stage.DATA_CACHE) return diskCacheStrategy.decodeCachedData()     ? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);      case DATA_CACHE: //如果只能从缓存中获取数据,则直接返回 FINISHED,否则,返回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);    }  }

由于我们什么都没有配置,返回的是 SourceGenerator 源数据执行器。继续下面代码执行:
runGenerators()

  private void runGenerators() {    // ...     while (!isCancelled && currentGenerator != null && !(isStarted = currentGenerator.startNext())) {      stage = getNextStage(stage);      currentGenerator = getNextGenerator();      // ...  }

着重看 while循环里面的currentGenerator.startNext();
DataFetcherGenerator 是一个抽象类,那么这里执行的实现类是哪一个,可以参考下面说明:

Stage.RESOURCE_CACHE【状态标记】 ---- 从磁盘中获取缓存的资源数据【作用】 — ResourceCacheGenerator【执行器】

Stage.DATA_CACHE【状态标记】 ---- 从磁盘中获取缓存的源数据【作用】 — DataCacheGenerator【执行器】

Stage.SOURCE【状态标记】 — 一次新的请求任务 — SourceGenerator【执行器】

因为这里我们没有配置缓存,那么直接看 SourceGenerator
在这里插入图片描述

  @Override  public boolean startNext() {...    loadData = null;    boolean started = false;    while (!started && hasNextModelLoader()) {      //获取一个 ModelLoad 加载器      loadData = helper.getLoadData().get(loadDataListIndex++);      if (loadData != null   && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())   || helper.hasLoadPath(loadData.fetcher.getDataClass()))) { started = true; //使用加载器中的 fetcher 根据优先级加载数据 loadData.fetcher.loadData(helper.getPriority(),  new DataCallback<Object>() {   @Override   public void onDataReady(@Nullable Object data) {     if (isCurrentRequest(toStart)) {     //这里需要记住,后面资源准备好之后 ,会回调到这里onDataReadyInternal(toStart, data);     }   }   @Override   public void onLoadFailed(@NonNull Exception e) {     if (isCurrentRequest(toStart)) {onLoadFailedInternal(toStart, e);     }   } });      }    }    return started;  }

helper.getLoadData() 获取的是一个什么样的加载器,我们可以先猜一下,因为没有配置任何缓存,所以可以猜得到是 http 请求了,那么是不是猜测的那样的,我们一起来验证下。

List<LoadData<?>> getLoadData() {    if (!isLoadDataSet) {      isLoadDataSet = true;      loadData.clear();//从 Glide 注册的 Model 来获取加载器(注册是在 Glide 初始化的时候通过 registry// .append()添加的)      List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);    for (int i = 0, size = modelLoaders.size(); i < size; i++) { ModelLoader<Object, ?> modelLoader = modelLoaders.get(i); LoadData<?> current =   //开始构建加载器     modelLoader.buildLoadData(model, width, height, options); //如果架子啊器不为空,那么添加进临时缓存 if (current != null) {   loadData.add(current); }      }    }    return loadData;  }

首先拿到一个加载器的容器,加载器是在 Glide 初始化的时候 通过 Registry.append() 添加的,这里我们以网络链接举例的。所以,ModelLoad 的实现类是 HttpGlideUrlLoader 加载器,我们看下它的具体实现:
在这里插入图片描述

  @Override  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);    // 看这里,TMD 终于看见Glide 网络加载器了    return new LoadData<>(url, new HttpUrlFetcher(url, timeout));  }

看到是返回的一个HttpUrlFetcher 给加载器。加载器我们拿到了,现在开始加载,返回到刚刚的源码,请看下面:

  @Override  public boolean startNext() {  // ...     while (!started && hasNextModelLoader()) {      loadData = helper.getLoadData().get(loadDataListIndex++);      if (loadData != null   && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) { started = true; startNextLoad(loadData);      }    }    return started;  }    private void startNextLoad(final LoadData<?> toStart) {    loadData.fetcher.loadData(...);  }  
  @Override  public void loadData(...) {  //...     //http 请求,返回一个 InputStream 输入流      InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());      //将 InputStream 以回调形式回调出去      callback.onDataReady(result);   //...  }  private InputStream loadDataWithRedirects(...) {   // ...    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);    // 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();    // ...  }

至此,终于找到网络请求了,这里是 HttpURLConnection 作为 Glide 底层成网络请求的。请求成功之后直接返回的是一个输入流,最后会通过 callback.onDataReady(result); 回调到 DecodeJob onDataFetcherReady 函数中。同学们我们跟下回调,回调到 SourceGenerator
在这里插入图片描述

loadData.fetcher.loadData(helper.getPriority(),  new DataCallback<Object>() {   @Override   public void onDataReady(@Nullable Object data) {     if (isCurrentRequest(toStart)) {     //这里需要记住,后面资源准备好之后 ,会回调到这里onDataReadyInternal(toStart, data);     }   }   @Override   public void onLoadFailed(@NonNull Exception e) {     if (isCurrentRequest(toStart)) {onLoadFailedInternal(toStart, e);     }   } });

前面调用loadData.fetcher.loadData方法重写了onDataReady,所以有继续调用onDataReadyInternal

  void onDataReadyInternal(LoadData<?> loadData, Object data) {    DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();    if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {      dataToCache = data;      // We might be being called back on someone else's thread. Before doing anything, we should      // reschedule to get back onto Glide's thread.      cb.reschedule();    } else {// 由于没有配置缓存,所以继续回调到 DecodeJob --》onDataFetcherRead      cb.onDataFetcherReady(   loadData.sourceKey,   data,   loadData.fetcher,   loadData.fetcher.getDataSource(),   originalKey);    }  }
   @Override      public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,   DataSource dataSource, Key attemptedKey) { this.currentSourceKey = sourceKey; //当前返回数据的 key this.currentData = data; //返回的数据 this.currentFetcher = fetcher; //返回的数据执行器,这里可以理解为 HttpUrlFetcher this.currentDataSource = dataSource; //数据来源 url this.currentAttemptingKey = attemptedKey; if (Thread.currentThread() != currentThread) {   runReason = RunReason.DECODE_DATA;   callback.reschedule(this); } else {   GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");   try {     //解析返回回来的数据     decodeFromRetrievedData();   } finally {     GlideTrace.endSection();   } }      }   //解析返回的数据  private void decodeFromRetrievedData() {    Resource<R> resource = null;    try {      // 调用 decodeFrom 解析 数据;HttpUrlFetcher , InputStream ,  currentDataSource      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);    stage = Stage.ENCODE;    try {      //这里就是将资源磁盘缓存      if (deferredEncodeManager.hasResourceToEncode()) { deferredEncodeManager.encode(diskCacheProvider, options);      }    } finally {     ...    }//完成    onEncodeComplete();  }  private void notifyComplete(Resource<R> resource, DataSource dataSource) {    setNotifiedOrThrow();    // 在 DecodeJob 的构建中, 我们知道这个 Callback 是 EngineJob    callback.onResourceReady(resource, dataSource);  }}

可以看到上面的 DecodeJob.decodeFromRetrievedData 中主要做了三个处理:

第一个处理:解析返回回来的资源。

第二个处理:拿到解析的资源,如果配置了本地缓存,就缓存到磁盘。

第三个处理:通知上层资源准备就绪,可以使用了。

同学们我们直接看 EngineJob 的 onResourceReady 回调函数:

  @Override  public void onResourceReady(Resource<R> resource, DataSource dataSource) {    synchronized (this) {      this.resource = resource;      this.dataSource = dataSource;    }    notifyCallbacksOfResult();  }void notifyCallbacksOfResult() {  // ...//回调上层 Engine 任务完成了    engineJobListener.onEngineJobComplete(this, localKey, localResource);    //遍历资源回调给 ImageViewTarget     for (final ResourceCallbackAndExecutor entry : copy) {      entry.executor.execute(new CallResourceReady(entry.cb));    }  }

通过上面 EngineJob 的 onResourceReady 回调函数 主要做了 两个处理:

​ 第一个处理:通知上层任务完成。

​ 第二个处理:回调 ImageViewTarget 用于展示数据

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)) {  ...   //返回准备好的资源   callCallbackOnResourceReady(cb);   removeCallback(cb); } decrementPendingCallbacks();      }    }  }
  @Synthetic  synchronized void callCallbackOnResourceReady(ResourceCallback cb) {    try {      //回调给 SingleRequest      cb.onResourceReady(engineResource, dataSource);    } catch (Throwable t) {      throw new CallbackException(t);    }  }
  @Override  public void onResourceReady(Resource<?> resource, DataSource dataSource) {    // ...    //当资源准备好的时候      onResourceReady((Resource<R>) resource, (R) received, dataSource);      // ...  }  private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {    // ...      if (!anyListenerHandledUpdatingTarget) { Transition<? super R> animation = animationFactory.build(dataSource, isFirstResource); //回调给目标 ImageViewTarget 资源准备好了 target.onResourceReady(result, animation);      }notifyLoadSuccess();  }
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)) {      setResourceInternal(resource);    } else {      maybeUpdateAnimatable(resource);    }  } private void setResourceInternal(@Nullable Z resource) {    setResource(resource);    maybeUpdateAnimatable(resource);  }  protected abstract void setResource(@Nullable Z resource);}

在最开始构建的时候,我们知道只有调用 asBitmap 的时候实现类是 BitmapImageViewTarget,在这里的测试,并没有调用这个函数,所以它的实现类是 DrawableImageViewTarget,具体看下它内部实现:

public class DrawableImageViewTarget extends ImageViewTarget<Drawable> {  public DrawableImageViewTarget(ImageView view) {    super(view);  }  /** @deprecated Use {@link #waitForLayout()} instead. */  // Public API.  @SuppressWarnings({"unused", "deprecation"})  @Deprecated  public DrawableImageViewTarget(ImageView view, boolean waitForLayout) {    super(view, waitForLayout);  }  @Override  protected void setResource(@Nullable Drawable resource) {    view.setImageDrawable(resource);  }}

这里看到抽象类中调用了 setResource ,子类实现并调用了 view.setImageDrawable(resource); 图片现在算是真正的显示出来了

是否已经淹死在源码里了