Glide源码分析之一

本篇作为Glide源码分析的开篇,以最简单的方式使用Glide,分析,最终图片是如何显示到ImageView上的。

Glide 版本:4.12.0

先说下结论:

  1. 首先获取View的宽高信息,通过ViewTreeObserver 的addOnPreDrawListener,在View将要绘制之前返回宽高信息。
  2. onSizeReady之后,先尝试使用 ResourceCacheGenerator 从包含对原始数据应用了采样或者变换(downsampled/transformed)的磁盘缓存获取。
  3. 尝试DataCacheGenerator 从没有修改过的原始磁盘缓存文件获取。
  4. 使用 SourceGenerator 从网络下载源数据。根据磁盘缓存策略,源数据可能首先被写入磁盘,然后从缓存文件加载,而不是直接返回。
  5. 有了磁盘缓存以后,再次使用 DataCacheGenerator 从没有修改过的原始磁盘缓存文件获取。这个时候就可以获取到数据并返回了。(猜测在这个过程中,还会做transform相关的操作,并把操作后的结果缓存到文件,这块没有去看。)
  6. 再次加载同一张图片,内存中已经有缓存了,直接从缓存获取返回。

最简单的使用方式

/**
 * 最简单的使用方式
 */
private void sourceCodeTest() {
    Glide.with(this)
		.load(Images.imageUrls[1])
		.into(imageView1);
}

with 方法返回的是 RequestManager 对象。

RequestManager 的 load 方法。

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

RequestManager 的 asDrawable 方法。

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

最终是构建了一个 RequestBuilder 对象。

RequestBuilder 的 load方法。

@NonNull
private RequestBuilder <TranscodeType> loadGeneric(@Nullable Object model) {
    if(isAutoCloneEnabled()) {
        return clone().loadGeneric(model);
    }
    //model 就是 要加载的图片链接
    this.model = model;
    //将 isModelSet 置为true
    isModelSet = true;
    //最终返回了RequestBuilder本身,没有什么特殊的设置
    return selfOrThrowIfLocked();
}

RequestBuilder 的 into 方法

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

    BaseRequestOptions <?> requestOptions = this;
    //注释1处,如果没有设置Transformation && 允许Transformation && view 的 ScaleType 不为null,则获取 requestOptions 对象。
    if(!requestOptions.isTransformationSet() && requestOptions.isTransformationAllowed() &&
        view.getScaleType() != null) {
        // Clone in this method so that if we use this RequestBuilder to load into a View and then
        // into a different target, we don't retain the transformation applied based on the previous
        // View's scale type.
		
		//在此方法中进行克隆,这样,如果我们使用此RequestBuilder加载到一个View中,然后加载到另一个目标中,
		//则不会保留基于上一个视图的缩放类型应用的转换。
        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.
        }
    }

    //注释2处,调用重载的 into 方法
    return into(
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/
        null,
        requestOptions,
        Executors.mainThreadExecutor());
}

注释1处,如果没有设置Transformation && 允许Transformation && view 的 ScaleType 不为null,则获取 requestOptions 对象。

注释2处,调用重载的 into 方法。

RequestBuilder 的 into 方法。

private <Y extends Target<TranscodeType>> Y into(@NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> options, Executor callbackExecutor) {
    //注释1处,在我们的例子中,target 是 DrawableImageViewTarget 对象。
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }
  
    //注释2处,构建request,我们先忽略其中的细节
    Request request = buildRequest(target, targetListener, options, callbackExecutor);

    Request previous = target.getRequest();
    //注释3处,如果有和之前的请求相同的请求,并且不是跳过内存缓存的请求,则使用之前的请求。
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
  
      if (!Preconditions.checkNotNull(previous).isRunning()) {
        previous.begin();
      }
      return target;
    }
    //注释4处,取消Glide可能为此target的所有未完成的加载,并释放可能已为目标加载的任何资源(例如{@link Bitmap}),以便可以重用它们。
    //注意:这里内部会清除Glide为Target设置的Tag。
    requestManager.clear(target);
    //注释5处,给target重新设置tag
    target.setRequest(request);
    //注释6处,跟踪请求
    requestManager.track(target, request);

    return target;
  }

注释1处,在我们的例子中,target 是 DrawableImageViewTarget 对象。

注释2处,构建request,我们先忽略其中的细节。返回的是一个 SingleRequest 对象。

注释3处,如果有和之前的请求相同的请求,并且不是跳过内存缓存的请求,则使用之前的请求。我们先忽略这种情况。

注释4处,取消Glide可能为此 target 的所有未完成的加载,并释放可能已为目标加载的任何资源(例如{@link Bitmap}),以便可以重用它们。 注意:这里内部会清除Glide为Target设置的Tag。

RequestManager 的 clear 方法。这块细节先略过。分析Glide在RecyclerView中应用的时候, 再详细分析。

注释5处,清除tag以后,给target重新设置tag。这个是保证不乱序的原因。

ViewTarget 的setRequest方法。

@Override
public void setRequest(@Nullable Request request) {
  setTag(request);
}
//tagId
private static int tagId = R.id.glide_custom_view_target_tag;

private void setTag(@Nullable Object tag) {
  //清除的时候,会将Tag设置为null。
  isTagUsedAtLeastOnce = true;
  view.setTag(tagId, tag);
}

RequestBuilder 的 into 方法注释6处, RequestManager 调用 track 方法。

synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
    targetTracker.track(target);
    //调用 RequestTracker 的 runRequest 方法 
    requestTracker.runRequest(request);
}

RequestTracker 的 runRequest 方法。

public void runRequest(@NonNull Request request) {
    requests.add(request);
    if(!isPaused) {
        //注释1处,调用 SingleRequest 的 begin 方法。
        request.begin();
    } else {
        request.clear();
        if(Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "Paused, delaying request");
        }
        pendingRequests.add(request);
    }
}

注释1处,调用 SingleRequest 的 begin 方法。

@Override
public void begin() {
    synchronized(requestLock) {
        assertNotCallingCallbacks();
        stateVerifier.throwIfRecycled();
        startTime = LogTime.getLogTime();
        if(model == null) {
            if(Util.isValidDimensions(overrideWidth, overrideHeight)) {
                width = overrideWidth;
                height = overrideHeight;
            }
            // Only log at more verbose log levels if the user has set a fallback drawable, because
            // fallback Drawables indicate the user expects null models occasionally.
            int logLevel = getFallbackDrawable() == null ? Log.WARN :
                Log.DEBUG;
            onLoadFailed(new GlideException("Received null model"),
                logLevel);
            return;
        }

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

        // If we're restarted after we're complete (usually via something like a notifyDataSetChanged
        // that starts an identical request into the same Target or View), we can simply use the
        // resource and size we retrieved the last time around and skip obtaining a new size, starting
        // a new load etc. This does mean that users who want to restart a load because they expect
        // that the view size has changed will need to explicitly clear the View or Target before
        // starting the new load.
        if(status == Status.COMPLETE) {
            onResourceReady(
                resource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */
                false);
            return;
        }

        // Restarts for requests that are neither complete nor running can be treated as new requests
        // and can run again from the beginning.

		//注释1处,开始状态是 WAITING_FOR_SIZE,等待控件测量过后有尺寸
        status = Status.WAITING_FOR_SIZE;
        if(Util.isValidDimensions(overrideWidth, overrideHeight)) {
            //注释2处,如果指定了宽高,直接调用onSizeReady方法。
            onSizeReady(overrideWidth, overrideHeight);
        } else {
            //注释3处,否则,调用Target的getSize方法。SingleRequest 本身做为回调传入
            target.getSize(this);
        }

        if((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE) &&
            canNotifyStatusChanged()) {
            //先给ImageView 设置placeholderDrawable
            target.onLoadStarted(getPlaceholderDrawable());
        }
        if(IS_VERBOSE_LOGGABLE) {
            logV("finished run method in " + LogTime.getElapsedMillis(
                startTime));
        }
    }
}

注释1处,开始状态是 WAITING_FOR_SIZE,等待控件测量过后有宽高信息。
注释2处,如果指定了宽高,直接调用onSizeReady方法。

注释3处,否则,调用Target的getSize方法。SingleRequest 本身做为回调传入。内部是调用 SizeDeterminer 的 getSize 方法。

void getSize(@NonNull SizeReadyCallback cb) {
    int currentWidth = getTargetWidth();
    int currentHeight = getTargetHeight();
    if(isViewStateAndSizeValid(currentWidth, currentHeight)) {
        //如果有宽高信息了,直接回调 onSizeReady 方法
        cb.onSizeReady(currentWidth, currentHeight);
        return;
    }
	//没有宽高信息,叫回调cb添加到列表中,等待获取到宽高信息后,通知回调cb。
    if(!cbs.contains(cb)) {
        cbs.add(cb);
    }
    if(layoutListener == null) {
        ViewTreeObserver observer = view.getViewTreeObserver();
        layoutListener = new SizeDeterminerLayoutListener(this);
        //注释1处,添加监听,监听尺寸的变化,在View绘制之前会执行这个layoutListener,此时已经有宽高信息了。
        observer.addOnPreDrawListener(layoutListener);
    }
}

注释1处,添加监听,监听尺寸的变化,在View绘制之前会执行这个layoutListener,此时已经有宽高信息了。

ViewTarget.SizeDeterminer.SizeDeterminerLayoutListener 类

private static final class SizeDeterminerLayoutListener
implements ViewTreeObserver.OnPreDrawListener {
    private final WeakReference <SizeDeterminer> sizeDeterminerRef;

    SizeDeterminerLayoutListener(@NonNull SizeDeterminer sizeDeterminer) {
        sizeDeterminerRef = new WeakReference <> (sizeDeterminer);
    }

    @Override
    public boolean onPreDraw() {
        SizeDeterminer sizeDeterminer = sizeDeterminerRef.get();
        if(sizeDeterminer != null) {
            //注释1处,调用 SizeDeterminer 的 checkCurrentDimens 方法。
            sizeDeterminer.checkCurrentDimens();
        }
        return true;
    }
}

注释1处,获取大调用 SizeDeterminer 的 checkCurrentDimens 方法。

@Synthetic
void checkCurrentDimens() {
    if(cbs.isEmpty()) {
        return;
    }

    //注释1处,注意,getTartgetWidth和getTargetHeight方法
    int currentWidth = getTargetWidth();
    int currentHeight = getTargetHeight();
    if(!isViewStateAndSizeValid(currentWidth, currentHeight)) {
        //注释2处,宽高不合法,说明此时View还没有经过measure,直接返回,SizeDeterminerLayoutListener不会被清除。
		//等待经过measure后,再次调用checkCurrentDimens方法。
        return;
    }

    //注释3处,如果宽高合法通知回调,并清除监听SizeDeterminerLayoutListener。
    notifyCbs(currentWidth, currentHeight);
    clearCallbacksAndListener();
}

注释1处,注意,SizeDeterminer 的 getTargetWidth 和 getTargetHeight 方法。

private int getTargetWidth() {
    int horizontalPadding = view.getPaddingLeft() + view.getPaddingRight();
    LayoutParams layoutParams = view.getLayoutParams();
    int layoutParamSize = layoutParams != null ? layoutParams.width :
        PENDING_SIZE;
    return getTargetDimen(view.getWidth(), layoutParamSize,
        horizontalPadding);
}

SizeDeterminer 的 getTargetDimen 方法。

    private int getTargetDimen(int viewSize, int paramSize, int paddingSize) {
        int adjustedParamSize = paramSize - paddingSize;
        if(adjustedParamSize > 0) {
            return adjustedParamSize;
        }
        
        if(waitForLayout && view.isLayoutRequested()) {
            return PENDING_SIZE;
        }

        int adjustedViewSize = viewSize - paddingSize;
        if(adjustedViewSize > 0) {
            return adjustedViewSize;
        }

        if(!view.isLayoutRequested() && paramSize == LayoutParams.WRAP_CONTENT) {
            //注释1处,获取屏幕的宽高中最大者,作为尺寸
            return getMaxDisplayLength(view.getContext());
        }

        // If the layout parameters are < padding, the view size is < padding, or the layout
        // parameters are set to match_parent or wrap_content and no layout has occurred, we should
        // wait for layout and repeat.
        return PENDING_SIZE;
    }

注释1处,注意一下,如果无法正确获取View的宽或者高,则获取屏幕的宽高中最大者,作为尺寸。

回到 SizeDeterminer 的 checkCurrentDimens 方法的注释2处,如果宽高不合法,说明此时View还没有经过measure,直接返回,SizeDeterminerLayoutListener 不会被清除。等待经过 measure 后,再次调用 checkCurrentDimens 方法。

注释3处,如果宽高合法,回调 onSizeReady 方法,并清除监听 SizeDeterminerLayoutListener。

获取到尺寸以后,回到 SingleRequest 的 onSizeReady 方法。

@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);

        //注释1处,调用Engine的load方法,开始加载图片
        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;
        }
    }
}

注释1处,调用 Engine 的 load 方法,开始加载图片。

/**
  * 开始加载给定参数的资源。
  *
  * <p>必须在主线程上调用。
  *
  * <p>任何请求的流程如下:
  *
  * <ul>
  *   <li>检查当前的活动资源集,如果存在则返回活动资源,并将任何新的非活动资源移动到内存缓存中。
  *   <li>检查内存缓存并提供缓存的资源(如果存在)。
  *   <li>检查当前的进行中的加载,并将cb添加到进行中的加载(如果存在)。
  *   <li>开始新的加载。
  * </ul>
  *
  * <p>活动资源是那些已经提供给至少一个请求并且尚未释放的资源。一旦资源的所有消费者都释放了该资源,该资源就会进入缓存。如果资源从缓存中返回给新的消费者,它将被重新添加到活动资源中。如果资源从缓存中被逐出,其资源将被回收并在可能的情况下重用,资源将被丢弃。消费者没有严格的要求释放他们的资源,所以活动资源被弱引用持有。
  *
  * @param width 目标资源的目标宽度(以像素为单位)。
  * @param height 目标资源的目标高度(以像素为单位)。
  * @param cb 当加载完成时将被调用的回调。
  */
public <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;

    EngineKey key =
        keyFactory.buildKey(
            model,
            signature,
            width,
            height,
            transformations,
            resourceClass,
            transcodeClass,
            options);

    EngineResource<?> memoryResource;
    synchronized (this) {
      //注释1处,先从内存加载  
      memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);

      if (memoryResource == null) {
        //注释2处,内存为null,检查当前的进行中的加载,并将cb添加到进行中的加载(如果存在)。不存在的话,开始新的加载。
        return waitForExistingOrStartNewJob(
            glideContext,
            model,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            options,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache,
            cb,
            callbackExecutor,
            key,
            startTime);
      }
    }

	//注释3处,内存存在的话,会直接回调onResourceReady方法
    cb.onResourceReady(
        memoryResource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);
    return null;
  }

注释1处,先从内存加载 。
注释3处,内存存在的话,会直接回调onResourceReady方法

注释2处,内存为null,检查当前的进行中的加载,并将cb添加到进行中的加载(如果存在)。不存在的话,开始新的加载。

Engine 的 waitForExistingOrStartNewJob 方法

private <R> LoadStatus waitForExistingOrStartNewJob(
    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,
    EngineKey key,
    long startTime) {

    //注释1处,存在正在进行的加载,将cb添加到进行中的加载,直接返回。
    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(
            key,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache);
    //构建一个解析对象,负责从缓存或者原始资源解析并应用transformations 和 transcodes
    DecodeJob <R> decodeJob = decodeJobFactory.build(
            glideContext,
            model,
            key,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            onlyRetrieveFromCache,
            options,
            engineJob);
	
    jobs.put(key, engineJob);
    engineJob.addCallback(cb, callbackExecutor);
    //注释2处,开始加载的地方
    engineJob.start(decodeJob);

    return new LoadStatus(cb, engineJob);
}

注释1处,存在正在进行的加载,将cb添加到进行中的加载,直接返回。

注释2处,开始加载的地方 EngineJob 的 start 方法

public synchronized void start(DecodeJob<R> decodeJob) {
    this.decodeJob = decodeJob;
    GlideExecutor executor =
        decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
    //调用 GlideExecutor 的 execute 方法
    executor.execute(decodeJob);
}

GlideExecutor 的 execute 方法

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

最终会执行 传入的 DecodeJob 的 run 方法

 @Override
  public void run() {
    // This should be much more fine grained, but since Java's thread pool implementation silently
    // swallows all otherwise fatal exceptions, this will at least make it obvious to developers
    // that something is failing.
    GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)", model);
    // Methods in the try statement can invalidate currentFetcher, so set a local variable here to
    // ensure that the fetcher is cleaned up either way.
    DataFetcher<?> localFetcher = currentFetcher;
    try {
      if (isCancelled) {
        notifyFailed();
        return;
      }
      //注释1处,调用 runWrapped 方法
      runWrapped();
    } catch (CallbackException e) {
      // If a callback not controlled by Glide throws an exception, we should avoid the Glide
      // specific debug logic below.
      throw e;
    } catch (Throwable t) {
      
      if (stage != Stage.ENCODE) {
        throwables.add(t);
        notifyFailed();
      }
      if (!isCancelled) {
        throw t;
      }
      throw t;
    } finally {
      // Keeping track of the fetcher here and calling cleanup is excessively paranoid, we call
      // close in all cases anyway.
      if (localFetcher != null) {
        localFetcher.cleanup();
      }
      GlideTrace.endSection();
    }
  }

注释1处,调用 DecodeJob 的 runWrapped 方法。

private void runWrapped() {
    switch(runReason) {
        case INITIALIZE:
            //注释1处,INITIALIZE 的下一个状态 RESOURCE_CACHE; 
            //下一个生成器 ResourceCacheGenerator
            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);
    }
}


注释1处,INITIALIZE 的下一个状态 RESOURCE_CACHE; 下一个生成器 ResourceCacheGenerator(这个貌似是负责从磁盘获取的操作)。
然后调用 DecodeJob 的 runGenerators 方法

private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    //注释1处,循环调用 startNext 方法
    while(!isCancelled && currentGenerator != null && !(isStarted = currentGenerator.startNext())) {
        stage = getNextStage(stage);
        currentGenerator = getNextGenerator();

        if(stage == Stage.SOURCE) {
            reschedule();
            return;
        }
    }
    // We've run out of stages and generators, give up.
    if((stage == Stage.FINISHED || isCancelled) && !isStarted) {
        notifyFailed();
    }

    // Otherwise a generator started a new load and we expect to be called back in
    // onDataFetcherReady.
}

注释1处,循环调用 startNext 方法。

第一次进入循环,调用 ResourceCacheGenerator 的 startNext 方法。
ResourceCacheGenerator:Generates DataFetchers from cache files containing downsampled/transformed resource data.

@Override
public boolean startNext() {
    List <Key> sourceIds = helper.getCacheKeys();
    if(sourceIds.isEmpty()) {
        return false;
    }
    /**
	 * 注册的资源类有
	 * 1. class com.bumptech.glide.load.resource.gif.GifDrawable
	 * 2. class android.graphics.Bitmap
	 * 3. class android.graphics.drawable.BitmapDrawable
	 */
    List <Class <?>> resourceClasses = helper.getRegisteredResourceClasses();
    //...
    while(modelLoaders == null || !hasNextModelLoader()) {
        resourceClassIndex++;
        if(resourceClassIndex >= resourceClasses.size()) {
            sourceIdIndex++;
            if(sourceIdIndex >= sourceIds.size()) {
            	//注释0处,最后返回了false,这个时候是没有磁盘缓存的。
                return false;
            }
            resourceClassIndex = 0;
        }

        //注释1处,sourceId 就是图片地址
        Key sourceId = sourceIds.get(sourceIdIndex);
        Class <?> resourceClass = resourceClasses.get(resourceClassIndex);
        Transformation <? > transformation = helper.getTransformation(resourceClass);
        // PMD.AvoidInstantiatingObjectsInLoops Each iteration is comparatively expensive anyway,
        // we only run until the first one succeeds, the loop runs for only a limited
        // number of iterations on the order of 10-20 in the worst case.
        currentKey =
            new ResourceCacheKey( // NOPMD AvoidInstantiatingObjectsInLoops
                helper.getArrayPool(),
                sourceId,
                helper.getSignature(),
                helper.getWidth(),
                helper.getHeight(),
                transformation,
                resourceClass,
                helper.getOptions());
        //注释2处,获取缓存的磁盘文件
        cacheFile = helper.getDiskCache().get(currentKey);
        if(cacheFile != null) {
            sourceKey = sourceId;
            modelLoaders = helper.getModelLoaders(cacheFile);
            modelLoaderIndex = 0;
        }
    }

    loadData = null;
    boolean started = false;
    while(!started && hasNextModelLoader()) {
        ModelLoader < File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
        loadData =
            modelLoader.buildLoadData(
                cacheFile, helper.getWidth(), helper.getHeight(), helper.getOptions());
        if(loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
            started = true;
            loadData.fetcher.loadData(helper.getPriority(), this);
        }
    }

    return started;
}

经过debug,这个方法在注释0处,最后返回了false,这个时候是没有磁盘缓存的。

回到 DecodeJob 的 runGenerators 方法,继续循环调用 startNext 方法。

下一个阶段 DATA_CACHE,调用 DataCacheGenerator 的 startNext 方法。

DataCacheGenerator:Generates DataFetchers from cache files containing original unmodified source data.

@Override
public boolean startNext() {
    while(modelLoaders == null || !hasNextModelLoader()) {
        sourceIdIndex++;
        if(sourceIdIndex >= cacheKeys.size()) {
            //注释0处,
            return false;
        }

        //sourceId 是 图片url
        Key sourceId = cacheKeys.get(sourceIdIndex);
        // PMD.AvoidInstantiatingObjectsInLoops The loop iterates a limited number of times
        // and the actions it performs are much more expensive than a single allocation.
        @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
        Key originalKey = new DataCacheKey(sourceId, helper.getSignature());
        //获取磁盘文件
        cacheFile = helper.getDiskCache().get(originalKey);
        if(cacheFile != null) {
            this.sourceKey = sourceId;
            modelLoaders = helper.getModelLoaders(cacheFile);
            modelLoaderIndex = 0;
        }
    }

    loadData = null;
    boolean started = false;
    while(!started && hasNextModelLoader()) {
        ModelLoader < File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
        loadData =
            modelLoader.buildLoadData(
                cacheFile, helper.getWidth(), helper.getHeight(), helper.getOptions());
        if(loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
            started = true;
            loadData.fetcher.loadData(helper.getPriority(), this);
        }
    }
    return started;
}

经过debug,这个方法最后在注释0处返回了false。

回到 DecodeJob 的 runGenerators 方法,继续循环调用 startNext 方法。下一个阶段 SOURCE,currentGenerator 是 SourceGenerator

如果是 SOURCE 阶段,调用 reschedule 方法。

@Override
public void reschedule() {
    //runReason 变成了 SWITCH_TO_SOURCE_SERVICE;
    runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
    //重新执行
    callback.reschedule(this);
}

最终还是会调用 DecodeJob 的 runGenerators 方法,这个时候 runReason 变成了 SWITCH_TO_SOURCE_SERVICE 。

private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    //注释1处,循环调用 startNext 方法
    while(!isCancelled && currentGenerator != null && !(isStarted = currentGenerator.startNext())) {
        stage = getNextStage(stage);
        currentGenerator = getNextGenerator();

        if(stage == Stage.SOURCE) {
            reschedule();
            return;
        }
    }
    // We've run out of stages and generators, give up.
    if((stage == Stage.FINISHED || isCancelled) && !isStarted) {
        notifyFailed();
    }

    // Otherwise a generator started a new load and we expect to be called back in
    // onDataFetcherReady.
}

注释1处,循环调用 startNext 方法。这时候调用的是 SourceGenerator 的 startNext 方法。

SourceGenerator类的注释翻译为:使用注册的 ModelLoader 和提供的 model,从原始源数据生成 DataFetcher

根据磁盘缓存策略,源数据可能首先被写入磁盘,然后从缓存文件加载,而不是直接返回。

@Override
public boolean startNext() {
    if(dataToCache != null) {
    	//注释1处,此时不存在要缓存的数据
        Object data = dataToCache;
        dataToCache = null;
        cacheData(data);
    }

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

    loadData = null;
    boolean started = false;
    while(!started && hasNextModelLoader()) {
        loadData = helper.getLoadData().get(loadDataListIndex++);
        if(loadData != null && (helper.getDiskCacheStrategy().isDataCacheable(
                    loadData.fetcher.getDataSource()) ||
                helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
            started = true;
            //注释1处,startNextLoad 方法
            startNextLoad(loadData);
        }
    }
    //返回true
    return started;
}

注释1处,调用 SourceGenerator 的 startNextLoad 方法

private void startNextLoad(final LoadData <?> toStart) {
    // 注释1处,调用 MultiModelLoader.MultiFetcher 的 loadData 方法。
    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);
                }
            }
        });
}

注释1处,调用 MultiModelLoader.MultiFetcher 的 loadData 方法。

@Override
public void loadData(@NonNull Priority priority, @NonNull DataCallback <?super Data>
    callback) {
    this.priority = priority;
    this.callback = callback;
    exceptions = throwableListPool.acquire();
    //注释1处,调用 OkHttpStreamFetcher 的 loadData 方法。 回调是 MultiModelLoader.MultiFetcher 对象
    fetchers.get(currentIndex).loadData(priority, this);

    if(isCancelled) {
        cancel();
    }
}

注释1处,调用 OkHttpStreamFetcher 的 loadData 方法,从网络获取数据。

@Override
public void loadData(@NonNull Priority priority, @NonNull final DataCallback <?super InputStream> callback) {
    Request.Builder requestBuilder = new Request.Builder().url(url.toStringUrl());
    for(Map.Entry < String, String > headerEntry: url.getHeaders().entrySet()) {
        String key = headerEntry.getKey();
        requestBuilder.addHeader(key, headerEntry.getValue());
    }
    Request request = requestBuilder.build();
    this.callback = callback;
	
    //注释1处,构建一个请求,并加入到请求队列中。
    call = client.newCall(request);
    //回调是 OkHttpStreamFetcher 对象
    call.enqueue(this);
}

请求成功以后,回调 OkHttpStreamFetcher 的 onResponse 方法。

@Override
public void onResponse(@NonNull Call call, @NonNull Response response) {
    responseBody = response.body();
    if(response.isSuccessful()) {
        long contentLength = Preconditions.checkNotNull(responseBody).contentLength();
        stream = ContentLengthInputStream.obtain(responseBody.byteStream(),
            contentLength);
        //注释1处,回调 MultiModelLoader.MultiFetcher 的 onDataReady 方法。
        callback.onDataReady(stream);
    } else {
        callback.onLoadFailed(new HttpException(response.message(),
            response.code()));
    }
}

注释1处,回调 MultiModelLoader.MultiFetcher 的 onDataReady 方法

@Override
public void onDataReady(@Nullable Data data) {
    if(data != null) {
        //注释1处,最终会回调到 SourceGenerator 的 onDataReadyInternal 方法。
        callback.onDataReady(data);
    } else {
        startNextOrFail();
    }
}

注释1处,最终会回调到 SourceGenerator 的 onDataReadyInternal 方法。

@Synthetic
void onDataReadyInternal(LoadData <?> loadData, Object data) {
    DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
    if(data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
    	//注释0处,给 dataToCache 赋值,这个时候,有需要缓存的数据了
        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.
		//注释2处,再次调用 DecodeJob 的 reschedule 方法。
        cb.reschedule();
    } else {
        cb.onDataFetcherReady(
            loadData.sourceKey,
            data,
            loadData.fetcher,
            loadData.fetcher.getDataSource(),
            originalKey);
    }
}

注释0处,给 dataToCache 赋值,这个时候,有需要缓存的数据了。

注释1处,再次调用 DecodeJob 的 reschedule 方法。

最终还是会调用 DecodeJob 的 runGenerators 方法

private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    //注释1处,循环调用 startNext 方法
    while(!isCancelled && currentGenerator != null && !(isStarted = currentGenerator.startNext())) {
        stage = getNextStage(stage);
        currentGenerator = getNextGenerator();

        if(stage == Stage.SOURCE) {
            reschedule();
            return;
        }
    }
    // We've run out of stages and generators, give up.
    if((stage == Stage.FINISHED || isCancelled) && !isStarted) {
        notifyFailed();
    }
}

注释1处,循环调用 startNext 方法。这时候调用的是 SourceGenerator 的 startNext 方法。

@Override
public boolean startNext() {
    if(dataToCache != null) {
        //注释1处,这时候,dataToCache 不为空,调用 cacheData 方法。调用 cacheData 方法。
        Object data = dataToCache;
        dataToCache = null;
        cacheData(data);
    }

	//注释2处
    if(sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
        return true;
    }
    sourceCacheGenerator = null;

    loadData = null;
    boolean started = false;
    while(!started && hasNextModelLoader()) {
        loadData = helper.getLoadData().get(loadDataListIndex++);
        if(loadData != null && (helper.getDiskCacheStrategy().isDataCacheable(
                loadData.fetcher.getDataSource()) || helper.hasLoadPath(
                loadData.fetcher.getDataClass()))) {
            started = true;
            startNextLoad(loadData);
        }
    }
    return started;
}

注释1处,这时候,dataToCache 不为空,调用 cacheData 方法。

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());
        //注释1处,调用 DiskLruCacheWrapper 的 put 方法。
        helper.getDiskCache().put(originalKey, writer);
    } finally {
        loadData.fetcher.cleanup();
    }
    //注释2处,缓存完数据以后,构建了一个 DataCacheGenerator 对象。后面会用这个对象来加载缓存数据。
    sourceCacheGenerator =
        new DataCacheGenerator(Collections.singletonList(loadData.sourceKey),
            helper, this);
}

注释1处,调用 DiskLruCacheWrapper 的 put 方法。

@Override
public void put(Key key, Writer writer) {
    // We want to make sure that puts block so that data is available when put completes. We may
    // actually not write any data if we find that data is written by the time we acquire the lock.
    String safeKey = safeKeyGenerator.getSafeKey(key);
    writeLocker.acquire(safeKey);
    try {
        if(Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "Put: Obtained: " + safeKey + " for for Key: " + key);
        }
        try {
            // We assume we only need to put once, so if data was written while we were trying to get
            // the lock, we can simply abort.
            DiskLruCache diskCache = getDiskCache();
            Value current = diskCache.get(safeKey);
            if(current != null) {
                return;
            }

            DiskLruCache.Editor editor = diskCache.edit(safeKey);
            if(editor == null) {
                throw new IllegalStateException(
                    "Had two simultaneous puts for: " + safeKey);
            }
            try {
                //注释1处,构建文件,写入文件
                File file = editor.getFile(0);
                if(writer.write(file)) {
                    editor.commit();
                }
            } finally {
                editor.abortUnlessCommitted();
            }
        } catch(IOException e) {
            if(Log.isLoggable(TAG, Log.WARN)) {
                Log.w(TAG, "Unable to put to disk cache", e);
            }
        }
    } finally {
        writeLocker.release(safeKey);
    }
}

注释1处,构建文件,写入文件。

cacheData 方法注释2处,缓存完数据以后,构建了一个 DataCacheGenerator 对象。后面在 SourceGenerator 的 startNext方法注释2处 判断 sourceCacheGenerator 不为null,
会用这个对象继续来 startNext ,从而加载缓存数据。

DataCacheGenerator 的 startNext 方法

@Override
public boolean startNext() {
    while(modelLoaders == null || !hasNextModelLoader()) {
        sourceIdIndex++;
        if(sourceIdIndex >= cacheKeys.size()) {
            return false;
        }

        //图片url
        Key sourceId = cacheKeys.get(sourceIdIndex);
        // PMD.AvoidInstantiatingObjectsInLoops The loop iterates a limited number of times
        // and the actions it performs are much more expensive than a single allocation.
        @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
        Key originalKey = new DataCacheKey(sourceId, helper.getSignature());
        //注释1处,这里从磁盘缓存中获取缓存文件就不为null了。
        cacheFile = helper.getDiskCache().get(originalKey);
        if(cacheFile != null) {
            this.sourceKey = sourceId;
            /**
			 * 这里的modelLoaders 是一个 List<ModelLoader<File, ?>> 对象。
			 * 1. ByteBufferFileLoader
			 * 2. FileLoader
			 * 3. FileLoader
			 * 4. UnitModelLoader
			 * 
			 */
            modelLoaders = helper.getModelLoaders(cacheFile);
            modelLoaderIndex = 0;
        }
    }

    loadData = null;
    boolean started = false;
    while(!started && hasNextModelLoader()) {
        ModelLoader < File, ?> modelLoader = modelLoaders.get(
            modelLoaderIndex++);
        loadData =
            modelLoader.buildLoadData(
                cacheFile, helper.getWidth(), helper.getHeight(), helper.getOptions()
            );
        if(loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
            started = true;
            //注释1处,调用 ByteBufferFileLoader.ByteBufferFetcher 的 loadData 方法。
			
            loadData.fetcher.loadData(helper.getPriority(), this);
        }
    }
    //注释2处,返回true
    return started;
}

注释1处,调用 ByteBufferFileLoader.ByteBufferFetcher 的 loadData 方法。回调是 DataCacheGenerator 对象。

@Override
public void loadData(@NonNull Priority priority, @NonNull DataCallback <? super ByteBuffer> callback) {
    ByteBuffer result;
    try {
        //缓存文件是:
		// /data/user/0/com.hm.bitmaploadexample/cache/image_manager_disk_cache/7d2fca3704dc60f2da82b3484e656e6e35bee407249878dea160c8809af902f1.0
        result = ByteBufferUtil.fromFile(file);
        //回调 DataCacheGenerator 对象的 onDataReady 方法。
        callback.onDataReady(result);
    } catch(IOException e) {
        if(Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Failed to obtain ByteBuffer for file", e);
        }
        callback.onLoadFailed(e);
    }
}

DataCacheGenerator 对象的 onDataReady 方法。

@Override
public void onDataReady(Object data) {
    //回调 SourceGenerator 对象的 onDataFetcherReady 方法。
    cb.onDataFetcherReady(sourceKey, data, loadData.fetcher, DataSource.DATA_DISK_CACHE, sourceKey);
}

SourceGenerator 对象的 onDataFetcherReady 方法。

@Override
  public void onDataFetcherReady(
      Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) {
    // This data fetcher will be loading from a File and provide the wrong data source, so override
    // with the data source of the original fetcher
	//调用 MultiModelLoader.MultiFetcher 的 getDataSources 方法。
	//然后回调到 DecodeJob 的 onDataFetcherReady 方法。	
    cb.onDataFetcherReady(sourceKey, data, fetcher, loadData.fetcher.getDataSource(), sourceKey);
  }

DecodeJob 的 onDataFetcherReady 方法。

@Override
public void onDataFetcherReady(
    Key sourceKey, Object data, DataFetcher <? > fetcher, DataSource dataSource,
    Key attemptedKey) {
    this.currentSourceKey = sourceKey;
    //data 是一个 java.nio.DirectByteBuffer[pos=0 lim=437344 cap=437344] 对象
    this.currentData = data;
    this.currentFetcher = fetcher;
    this.currentDataSource = dataSource;
    this.currentAttemptingKey = attemptedKey;
    this.isLoadingFromAlternateCacheKey = sourceKey != decodeHelper.getCacheKeys()
        .get(0);

    if(Thread.currentThread() != currentThread) {
        runReason = RunReason.DECODE_DATA;
        callback.reschedule(this);
    } else {
        GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
        try {
		    //注释1处,解析数据
            decodeFromRetrievedData();
        } finally {
            GlideTrace.endSection();
        }
    }
}

注释1处,解析数据 DecodeJob 的 decodeFromRetrievedData 方法。

private void decodeFromRetrievedData() {
    Resource <R> resource = null;
    try {
        //注释1处,调用 DecodeJob 的 decodeFromData 方法。
        resource = decodeFromData(currentFetcher, currentData,
            currentDataSource);
    } catch(GlideException e) {
        e.setLoggingDetails(currentAttemptingKey, currentDataSource);
        throwables.add(e);
    }
    if(resource != null) {
        //注释2处,调用 DecodeJob 的 notifyEncodeAndRelease 方法。
        notifyEncodeAndRelease(resource, currentDataSource,
            isLoadingFromAlternateCacheKey);
    } else {
        runGenerators();
    }
}

注释1处,调用 DecodeJob 的 decodeFromData 方法。

private <Data> Resource<R> decodeFromData(
      DataFetcher<?> fetcher, Data data, DataSource dataSource) throws GlideException {
    try {
      if (data == null) {
        return null;
      }
      long startTime = LogTime.getLogTime();
      //注释1处,调用 DecodeJob 的 decodeFromFetcher 方法。
      Resource<R> result = decodeFromFetcher(data, dataSource);
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        logWithTimeAndKey("Decoded result " + result, startTime);
      }
      //注释2处,最终返回的是 LazyBitmapDrawableResource 对象。
      return result;
    } finally {
      fetcher.cleanup();
    }
  }

在我们的例子中,最终会调用 ByteBufferBitmapDecoder 的 decode 方法。

@Override
public Resource <Bitmap> decode(@NonNull ByteBuffer source, int width, int height, @NonNull Options options)
		throws IOException {
    InputStream is = ByteBufferUtil.toStream(source);
    return downsampler.decode(is, width, height, options);
}

注释2处,最终返回的是 LazyBitmapDrawableResource 对象。

解析完毕后,回到 decodeFromRetrievedData 方法 注释2处,调用 DecodeJob 的 notifyEncodeAndRelease 方法。

private void notifyEncodeAndRelease(
    Resource <R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey
) {
    if(resource instanceof Initializable) {
        ((Initializable) resource).initialize();
    }

    Resource <R> result = resource;
    LockedResource <R> lockedResource = null;
    if(deferredEncodeManager.hasResourceToEncode()) {
        lockedResource = LockedResource.obtain(resource);
        result = lockedResource;
    }

    //注释1处,调用 DecodeJob 的 notifyComplete 方法。通知成功
    notifyComplete(result, dataSource, isLoadedFromAlternateCacheKey);

    stage = Stage.ENCODE;
    try {
        if(deferredEncodeManager.hasResourceToEncode()) {
            deferredEncodeManager.encode(diskCacheProvider, options);
        }
    } finally {
        if(lockedResource != null) {
            lockedResource.unlock();
        }
    }
    // Call onEncodeComplete outside the finally block so that it's not called if the encode process
    // throws.
    onEncodeComplete();
}

注释1处,调用 DecodeJob 的 notifyComplete 方法。通知成功

private void notifyComplete(
      Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
    setNotifiedOrThrow();
    //回调 EngineJob 的 onResourceReady 方法。
    callback.onResourceReady(resource, dataSource, isLoadedFromAlternateCacheKey);
}

EngineJob 的 onResourceReady 方法。

@Override
public void onResourceReady(
      Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
    synchronized (this) {
      this.resource = resource;
      this.dataSource = dataSource;
      this.isLoadedFromAlternateCacheKey = isLoadedFromAlternateCacheKey;
    }
    //注释1处,调用 EngineJob 的 notifyCallbacksOfResult 方法。
    notifyCallbacksOfResult();
}

注释1处,调用 EngineJob 的 notifyCallbacksOfResult 方法。

@Synthetic
void notifyCallbacksOfResult() {
    ResourceCallbacksAndExecutors copy;
    Key localKey;
    EngineResource <?> localResource;
    synchronized(this) {
        stateVerifier.throwIfRecycled();
        if(isCancelled) {
            // TODO: Seems like we might as well put this in the memory cache instead of just recycling
            // it since we've gotten this far...
            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");
        }
        engineResource = engineResourceFactory.build(resource,
            isCacheable, key, resourceListener);
        // Hold on to resource for duration of our callbacks below so we don't recycle it in the
        // middle of notifying if it synchronously released by one of the callbacks. Acquire it under
        // a lock here so that any newly added callback that executes before the next locked section
        // below can't recycle the resource before we call the callbacks.
        hasResource = true;
        copy = cbs.copy();
        incrementPendingCallbacks(copy.size() + 1);

        localKey = key;
        localResource = engineResource;
    }

    engineJobListener.onEngineJobComplete(this, localKey, localResource);

    for(final ResourceCallbackAndExecutor entry: copy) {
        //注释1处,这里最终会调用 SingleRequest 的 onResourceReady 方法。
        entry.executor.execute(new CallResourceReady(entry.cb));
    }
    decrementPendingCallbacks();
}

注释1处,这里最终会调用 SingleRequest 的 onResourceReady 方法。

@Override
  public void onResourceReady(
      Resource<?> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
    stateVerifier.throwIfRecycled();
    Resource<?> toRelease = null;
    try {
      synchronized (requestLock) {
        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;
        }

        Object received = resource.get();
        if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
          toRelease = resource;
          this.resource = null;
          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()) {
          toRelease = resource;
          this.resource = null;
          // We can't put the status to complete before asking canSetResource().
          status = Status.COMPLETE;
          return;
        }

        //注释1处,调用重载的 onResourceReady 方法。
        onResourceReady(
            (Resource<R>) resource, (R) received, dataSource, isLoadedFromAlternateCacheKey);
      }
    } finally {
      if (toRelease != null) {
        engine.release(toRelease);
      }
    }
  }

注释1处,调用重载的 onResourceReady 方法。

private void onResourceReady(
    Resource <R> resource, R result, DataSource dataSource, boolean isAlternateCacheKey) {
    // We must call isFirstReadyResource before setting status.
    boolean isFirstResource = isFirstReadyResource();
    status = Status.COMPLETE;
    this.resource = resource;

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

    isCallingCallbacks = true;
    try {
        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);
            //注释1处,回调 DrawableImageViewTarget 的 onResourceReady 方法。
            target.onResourceReady(result, animation);
        }
    } finally {
        isCallingCallbacks = false;
    }

    notifyLoadSuccess();
}

注释1处,回调 DrawableImageViewTarget 的 onResourceReady 方法。会走到父类 ImageViewTarget 的 onResourceReady 方法。

ImageViewTarget 的 onResourceReady 方法。

@Override
public void onResourceReady(@NonNull Z resource, @Nullable Transition <? super Z >
    transition) {
    if(transition == null || !transition.transition(resource, this)) {
        //注释1处,调用 setResourceInternal 方法。
        setResourceInternal(resource);
    } else {
        maybeUpdateAnimatable(resource);
    }
}

ImageViewTarget 的 setResourceInternal 方法。

private void setResourceInternal(@Nullable Z resource) {
    // Order matters here. Set the resource first to make sure that the Drawable has a valid and
    // non-null Callback before starting it.
	//注释1处,调用 DrawableImageViewTarget 的 setResource 方法。	
    setResource(resource);
    maybeUpdateAnimatable(resource);
  }

注释1处,调用 DrawableImageViewTarget 的 setResource 方法。

 @Override
protected void setResource(@Nullable Drawable resource) {
    //这里最终给 ImageView 设置了resource,是一个BitmapDrawable。
    view.setImageDrawable(resource);
}

这里最终给 ImageView 设置了resource,是一个BitmapDrawable。

后续文章待完成。

  1. transform的处理,缓存的细节。
  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值