杨说:Glide 4.11.0 发送请求和缓存

1,766 阅读10分钟

上文说到Glide对请求的准备工作 杨说:Glide 4.11.0 发送请求准备工作 ,这篇分析Glide的请求和缓存。请求最后都是封装成了SingleRequest。

目录

一、请求入口
二、从内存中取图片
三、从磁盘获取取图片
四、从网络获取取图片
五、图片下载成功后回调
六、总结

一 请求入口

request.begin();执行的是SingleRequest的begin()方法

SingleRequest.java


@Override
  public void begin() {
  	//同步锁
    synchronized (requestLock) {
      ···
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
        //真正请求和缓存的地方
        onSizeReady(overrideWidth, overrideHeight);
      } else {
        ···
      }
      ···
    }
  }

使用Engine.load()加载图片数据

SingleRequest.java

public void onSizeReady(int width, int height) {
    stateVerifier.throwIfRecycled();
    synchronized (requestLock) {
      if (IS_VERBOSE_LOGGABLE) {
        logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
      }
      if (status != Status.WAITING_FOR_SIZE) {
        return;
      }
      status = Status.RUNNING;
	  //缩略图
      float sizeMultiplier = requestOptions.getSizeMultiplier();
      this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
      this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
	  ····
      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);
    ···
    }
  }

首先静态工厂方法创建引擎的key,使用签名,宽度,高度,变换,资源类,配置等作为生成key的参数

Engine.java

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;
    //通过静态工厂创建加载引擎的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);
      }
    }

    // Avoid calling back while holding the engine lock, doing so makes it easier for callers to
    // deadlock.
    cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
    return null;

二 从内存中取图片

2.1 从内存中取出图片

memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);从内存中加载图片

Engine.java

private EngineResource<?> loadFromMemory(
      EngineKey key, boolean isMemoryCacheable, long startTime) {
     //如果设置不从内存中取图片,直接返回null
    if (!isMemoryCacheable) {
      return null;
    }
	//获取正在显示的资源
    EngineResource<?> active = loadFromActiveResources(key);
    if (active != null) {
      ···
      return active;
    }
	//从缓存中加载图片
    EngineResource<?> cached = loadFromCache(key);
    if (cached != null) {
      ···
      return cached;
    }

    return null;
  }

2.1.1 从活动的图片中加载图片数据&增加图像引用计数

loadFromActiveResources(key);

Engine.java

private EngineResource<?> loadFromActiveResources(Key key) {
	//从缓存中取图像
    EngineResource<?> active = activeResources.get(key);
    if (active != null) {
   	  //增加引用计数
      active.acquire();
    }

    return active;
  }

2.1.1.1 从活动缓存中加载图片数据

ActiveResources.java

synchronized EngineResource<?> get(Key key) {
	//弱引用修饰图像引用
    ResourceWeakReference activeRef = activeEngineResources.get(key);
    if (activeRef == null) {
      return null;
    }
	
    EngineResource<?> active = activeRef.get();
    if (active == null) {
      //如果active为null 清空
      cleanupActiveReference(activeRef);
    }
    //返回缓存数据
    return active;
  }

2.2.1 从缓存中加载图片

loadFromCache(key); 通过可以在缓存中加载图片

Engine.java

private EngineResource<?> loadFromCache(Key key) {
	//从缓存重获取图像
    EngineResource<?> cached = getEngineResourceFromCache(key);
    if (cached != null) {
      //增加引用计数
      cached.acquire();
      //添加到活动的缓存中
      activeResources.activate(key, cached);
    }
    return cached;
  }

getEngineResourceFromCache(key);从缓存中获取图像数据

Engine.java

private EngineResource<?> getEngineResourceFromCache(Key key) {
    Resource<?> cached = cache.remove(key);

    final EngineResource<?> result;
    //封装返回结果
    if (cached == null) {
      result = null;
    } else if (cached instanceof EngineResource) {
      // Save an object allocation if we've cached an EngineResource (the typical case).
      result = (EngineResource<?>) cached;
    } else {
      result =
          new EngineResource<>(
              cached, /*isMemoryCacheable=*/ true, /*isRecyclable=*/ true, key, /*listener=*/ this);
    }
    return result;
  }

2.2.2 缓存的初始化

上面获取的缓存是MemoryCache类型的,可以在外部设置,在builder Glide配置时赋值

GlideBuilder.java

@NonNull
  Glide build(@NonNull Context context) {
    ···
    if (memoryCache == null) {
      //内存缓存
      memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
    }

    if (engine == null) {
      engine =
          new Engine(
              //这里将memoryCache传入到加载引擎
              memoryCache,
              diskCacheFactory,
              diskCacheExecutor,
              sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor(),
              animationExecutor,
              isActiveResourceRetentionAllowed);
    }
	
   ····

    return new Glide(
        context,
        engine,
        memoryCache,
        bitmapPool,
        arrayPool,
        requestManagerRetriever,
        connectivityMonitorFactory,
        logLevel,
        defaultRequestOptionsFactory,
        defaultTransitionOptions,
        defaultRequestListeners,
        isLoggingRequestOriginsEnabled,
        isImageDecoderEnabledForBitmaps);
  }

2.2.3 内存缓存LruResourceCache

LruResourceCache继承自LruCache,内部使用LinkedHashMap实现LRU算法,初始化大小100,装填因子0.75,所有方法都synchronized修饰保证同步

三 从磁盘中取图片

3.1 创建获取和解码图片任务

从Engine的load方法开始,如果从内存中没有取出图片,那么开始创建任务,从磁盘或者网络上取图片

Engine.java

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) {
      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);
      }
    }
Engine.java

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) {
	
   	//如果当前有任务直接取出任务
    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
      current.addCallback(cb, callbackExecutor);
      ···
      return new LoadStatus(cb, current);
    }
    //创建执行的任务
    EngineJob<R> engineJob =
        engineJobFactory.build(
            key,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache);
	//创建解码任务
    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);
	//设置任务的callback
    engineJob.addCallback(cb, callbackExecutor);
    //开始任务
    engineJob.start(decodeJob);
    ····
    return new LoadStatus(cb, engineJob);
  }

3.2 engineJob获取图片任务引擎

engineJob是通过工厂方法创建的

GlideBuilder.java

 Glide build(@NonNull Conext context) {
    ···

    if (engine == null) {
      //如果外部没有设置加载引擎那么直接创建一个
      engine =
          new Engine(
              memoryCache,
              diskCacheFactory,
              diskCacheExecutor,
              sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor(),
              animationExecutor,
              isActiveResourceRetentionAllowed);
    }

    ···
  }

Engine构造函数

Engine.java

public Engine(
      MemoryCache memoryCache,
      DiskCache.Factory diskCacheFactory,
      GlideExecutor diskCacheExecutor,
      GlideExecutor sourceExecutor,
      GlideExecutor sourceUnlimitedExecutor,
      GlideExecutor animationExecutor,
      boolean isActiveResourceRetentionAllowed) {
    this(
        memoryCache,
        diskCacheFactory,
        diskCacheExecutor,
        sourceExecutor,
        sourceUnlimitedExecutor,
        animationExecutor,
        /*jobs=*/ null,
        /*keyFactory=*/ null,
        /*activeResources=*/ null,
        /*engineJobFactory=*/ null,
        /*decodeJobFactory=*/ null,
        /*resourceRecycler=*/ null,
        isActiveResourceRetentionAllowed);
  }
  
Engine(
      MemoryCache cache,
      DiskCache.Factory diskCacheFactory,
      GlideExecutor diskCacheExecutor,
      GlideExecutor sourceExecutor,
      GlideExecutor sourceUnlimitedExecutor,
      GlideExecutor animationExecutor,
      Jobs jobs,
      EngineKeyFactory keyFactory,
      ActiveResources activeResources,
      EngineJobFactory engineJobFactory,
      DecodeJobFactory decodeJobFactory,
      ResourceRecycler resourceRecycler,
      boolean isActiveResourceRetentionAllowed) {
    ···

    if (engineJobFactory == null) {
      engineJobFactory =
          new EngineJobFactory(
              diskCacheExecutor,
              sourceExecutor,
              sourceUnlimitedExecutor,
              animationExecutor,
              /*engineJobListener=*/ this,
              /*resourceListener=*/ this);
    }
    ···
  }

3.3 开始获取图片任务

engineJob.start(decodeJob); 开始执行解码的任务,调用的是DecodeJob的run()

EngineJob.java

public synchronized void start(DecodeJob<R> decodeJob) {
    this.decodeJob = decodeJob;
    GlideExecutor executor =
        decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
    executor.execute(decodeJob);
  }
DecodeJob.java

public void run() {
    ···
    //赋值callback
    DataFetcher<?> localFetcher = currentFetcher;
    try {
      if (isCancelled) {
        notifyFailed();
        return;
      }
      //加载方法
      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();
      }
      ···
    } finally {
     ····
     //清空
      if (localFetcher != null) {
        localFetcher.cleanup();
      }
      GlideTrace.endSection();
    }
  }

调用runWrapped();开始执行任务

DecodeJob.java

private void runWrapped() {
    switch (runReason) {
    //第一次一定会调用这个
      case INITIALIZE:
        stage = getNextStage(Stage.INITIALIZE);
        currentGenerator = getNextGenerator();
        runGenerators();
        break;
      case SWITCH_TO_SOURCE_SERVICE:
        runGenerators();
        break;
      case DECODE_DATA:
        decodeFromRetrievedData();
        break;
      default:
        throw new IllegalStateException("Unrecognized run reason: " + runReason);
    }
  }

getNextStage(Stage.INITIALIZE);根据当前的状态获取加载数据的类型


private Stage getNextStage(Stage current) {
    switch (current) {
      case INITIALIZE:
      	//有解码的缓存返回Stage.RESOURCE_CACHE
        return diskCacheStrategy.decodeCachedResource()
            ? Stage.RESOURCE_CACHE
            : getNextStage(Stage.RESOURCE_CACHE);
      case RESOURCE_CACHE:
        //如果有磁盘荤菜返回Stage.DATA_CACHE
        return diskCacheStrategy.decodeCachedData()
            ? Stage.DATA_CACHE
            : getNextStage(Stage.DATA_CACHE);
      case DATA_CACHE:
        // Skip loading from source if the user opted to only retrieve the resource from cache.
        //如果只从缓存加载返回Stage.FINISHED否则 Stage.SOURCE
        return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
      case SOURCE:
      case FINISHED:
        return Stage.FINISHED;
      default:
        throw new IllegalArgumentException("Unrecognized stage: " + current);
    }
  }

getNextStage() 返回Stage到runWrapped(),然后调用getNextGenerator()根据不同的状态获取不同的加载数据的方式

DecodeJob.java

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

获取加载数据的方式返回到runWrapped(),调用

DecodeJob.java

private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    while (!isCancelled
        && currentGenerator != null
        //这里就是真正调用加载数据的地方
        && !(isStarted = currentGenerator.startNext())) {
      stage = getNextStage(stage);
      currentGenerator = getNextGenerator();

      if (stage == Stage.SOURCE) {
        reschedule();
        return;
      }
    }
    ····
  }

3.4 从磁盘缓存中获取数据

currentGenerator.startNext() 开始获取数据,其中有两个是磁盘的缓存ResourceCacheGenerator从磁盘中获取匹配宽高的缓存、DataCacheGenerator从磁盘中获取缓存

3.4.1 从磁盘中获取匹配宽高的缓存

ResourceCacheGenerator.java

 public boolean startNext() {
    List<Key> sourceIds = helper.getCacheKeys();
    ···
    List<Class<?>> resourceClasses = helper.getRegisteredResourceClasses();
    ····
    while (modelLoaders == null || !hasNextModelLoader()) {
      resourceClassIndex++;
      if (resourceClassIndex >= resourceClasses.size()) {
        sourceIdIndex++;
        if (sourceIdIndex >= sourceIds.size()) {
          return false;
        }
        resourceClassIndex = 0;
      }

      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.
      //当前缓存的key
      currentKey =
          new ResourceCacheKey( // NOPMD AvoidInstantiatingObjectsInLoops
              helper.getArrayPool(),
              sourceId,
              helper.getSignature(),
              helper.getWidth(),
              helper.getHeight(),
              transformation,
              resourceClass,
              helper.getOptions());
      //从key中获取文件
      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;
        //使用fetcher加载数据
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }

    return started;
  }

3.4.2 从磁盘中获取缓存

DataCacheGenerator.java

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

      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;
        //从fetcher中加载数据
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }
    return started;
  }

四 从网络获取图片

4.1 从网络获取缓存

currentGenerator.startNext() 开始获取数据,网络的实现类是SourceGenerator

SourceGenerator.java

 @Override
  public boolean startNext() {
    if (dataToCache != null) {
      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;
        //开始网络请求数据
        startNextLoad(loadData);
      }
    }
    return started;
  }
  
 //开始用网络获取数据
 private void startNextLoad(final LoadData<?> toStart) {
    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这个fetcher有很多实现类,网络的实现类是HttpUrlFetcher,调用loadData加载数据

HttpUrlFetcher.java

public void loadData(
      @NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
    long startTime = LogTime.getLogTime();
    try {
    //使用网络请求默认石使用HttpURLConnection
      InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
      //下载成功调用回调
      callback.onDataReady(result);
    } catch (IOException e) {
      ···
      //下载失败
      callback.onLoadFailed(e);
    } finally {
      ····
    }
  }

五 图片下载成功后回调

5.1 网络成功回调

SourceGenerator.java

private void startNextLoad(final LoadData<?> toStart) {
    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);
            }
          }
        });
  }
SourceGenerator.java

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 {
      //继续调用回调
      cb.onDataFetcherReady(
          loadData.sourceKey,
          data,
          loadData.fetcher,
          loadData.fetcher.getDataSource(),
          originalKey);
    }
  }
DecodeJob.java

public void onDataFetcherReady(
      Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) {
    this.currentSourceKey = sourceKey;
    this.currentData = data;
    this.currentFetcher = fetcher;
    this.currentDataSource = dataSource;
    this.currentAttemptingKey = attemptedKey;
    if (Thread.currentThread() != currentThread) {
      //回调到Glide调用线程
      runReason = RunReason.DECODE_DATA;
      //callback这个是创建DecodeJob的时候传入进来的他是EngineJob,callback
      callback.reschedule(this);
    } else {
      GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
      try {
      	//会调用EngineJob的onResourceReady
        decodeFromRetrievedData();
      } finally {
        GlideTrace.endSection();
      }
    }
  }
DecodeJob.java

 private void decodeFromRetrievedData() {
    ···
    Resource<R> resource = null;
    try {
      resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    } catch (GlideException e) {
      e.setLoggingDetails(currentAttemptingKey, currentDataSource);
      throwables.add(e);
    }
    if (resource != null) {
    //调用EngineJob,callback
      notifyEncodeAndRelease(resource, currentDataSource);
    } else {
      runGenerators();
    }
  }
DecodeJob.java

 private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
    if (resource instanceof Initializable) {
      ((Initializable) resource).initialize();
    }
···
 //调用EngineJob,callback
    notifyComplete(result, dataSource);

    ···
  }

到这里就调用到了调用EngineJob的onResourceReady方法

DecodeJob.java

 private void notifyComplete(Resource<R> resource, DataSource dataSource) {
    setNotifiedOrThrow();
    callback.onResourceReady(resource, dataSource);
  }
EngineJob.java

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

void notifyCallbacksOfResult() {
    ···
	//调用回调
    engineJobListener.onEngineJobComplete(this, localKey, localResource);

    for (final ResourceCallbackAndExecutor entry : copy) {
      //执行回调
      entry.executor.execute(new CallResourceReady(entry.cb));
    }
    decrementPendingCallbacks();
  }

执行CallResourceReadyde run方法

CallResourceReady.java

public void run() {
      // Make sure we always acquire the request lock, then the EngineJob lock to avoid deadlock
      // (b/136032534).
      //加锁
      synchronized (cb.getLock()) {
        synchronized (EngineJob.this) {
          if (cbs.contains(cb)) {
            // Acquire for this particular callback.
            //增加引用
            engineResource.acquire();
            callCallbackOnResourceReady(cb);
            removeCallback(cb);
          }
          decrementPendingCallbacks();
        }
      }
    }
EngineJob.java

void callCallbackOnResourceReady(ResourceCallback cb) {
    try {
      // This is overly broad, some Glide code is actually called here, but it's much
      // simpler to encapsulate here than to do so at the actual call point in the
      // Request implementation.
      cb.onResourceReady(engineResource, dataSource);
    } catch (Throwable t) {
      throw new CallbackException(t);
    }
  }

cb.onResourceReady(engineResource, dataSource);这个cb是final ResourceCallbacksAndExecutors cbs = new ResourceCallbacksAndExecutors()。他是一个几个存储监听成功的回调和执行器,他的赋值是在Engine的waitForExistingOrStartNewJob

Engine.java

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

   EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
   if (current != null) {
     //添加回调和执行器
     current.addCallback(cb, callbackExecutor);
     ···
     return new LoadStatus(cb, current);
   }

   EngineJob<R> engineJob =
       engineJobFactory.build(
           key,
           isMemoryCacheable,
           useUnlimitedSourceExecutorPool,
           useAnimationPool,
           onlyRetrieveFromCache);

   DecodeJob<R> decodeJob =
       decodeJobFactory.build(
           glideContext,
           model,
           key,
           signature,
           width,
           height,
           resourceClass,
           transcodeClass,
           priority,
           diskCacheStrategy,
           transformations,
           isTransformationRequired,
           isScaleOnlyOrNoTransform,
           onlyRetrieveFromCache,
           options,
           engineJob);

   jobs.put(key, engineJob);

   //添加回调和执行器
   engineJob.addCallback(cb, callbackExecutor);
   engineJob.start(decodeJob);

  ···
   return new LoadStatus(cb, engineJob);
 }

这个ResourceCallback类型cb是从Engine的load方法传入的,engine.load()是在SingleRequest中的onSizeReady()调用,并且onSizeReady实现了ResourceCallback

SingleRequest.java

 public void onSizeReady(int width, int height) {
    stateVerifier.throwIfRecycled();
    synchronized (requestLock) {
      ····
      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就是ResourceCallback
              this,
              callbackExecutor);

      ···
    }
  }

SingleRequest的onResourceReady

SingleRequest.java

public void onResourceReady(Resource<?> resource, DataSource dataSource) {
    stateVerifier.throwIfRecycled();
    Resource<?> toRelease = null;
    try {
      synchronized (requestLock) {
        loadStatus = null;
        if (resource == null) {
          ···
          //错误
          onLoadFailed(exception);
          return;
        }

        Object received = resource.get();
        if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
          ···
          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;
        }
        //调用处理数据
        onResourceReady((Resource<R>) resource, (R) received, dataSource);
      }
    } finally {
      if (toRelease != null) {
        engine.release(toRelease);
      }
    }
  }
SingleRequest.java

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

  ···

    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成功
              && targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);

      if (!anyListenerHandledUpdatingTarget) {
        Transition<? super R> animation = animationFactory.build(dataSource, isFirstResource);
         //调用target成功,这个target就是我们在外部设置的target
        target.onResourceReady(result, animation);
      }
    } finally {
      isCallingCallbacks = false;
    }

    notifyLoadSuccess();
  }

六 总结

1、调用into发送请求加载图片后,会先从内存中取图片,内存中图片会有计数器标记引用数。
2、活动缓存是一个Map<Key,WeakReference>类型,当前View正在显示,内存缓存是LruCache<Key, Resource<?>>类型,最近是否被加入到内存
3、如果内存不存在会从磁盘中取数据,ResourceCacheGenerator是带有宽高尺寸的磁盘缓存,DataCacheGenerator是不带有宽高的磁盘缓存
4、从网络获取数据默认是用HttpUrlConnection,也可以更换成OKHttp