Posts Glide请求过程分析
Post
Cancel

Glide请求过程分析

RequestManager会调用SingleRequestbegin方法发起一个请求,一个请求会经历如下过程。

  1. 如果没有设置加载的图片的宽高,则会获取对应ImageView的宽高。
  2. 获取图片的流。
  3. 调用Encoder,将流转化为文件。
  4. 获取文件流,并调用Decoder转化为Bitmap。
  5. 调用Downsampler进行重新采样。
  6. 调用Transformation实现变换操作。
  7. 调用TranscoderBitmap转码为Drawable.
  8. 调用ImageViewsetImageDrawable方法,将Drawable设置到ImageView上。

begin

如果设置了overrideWidth和overrideHeight,则调用onSizeReady,否则会调用TargetgetSize方法获取ImageView的宽高。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
@Override
public synchronized void begin() {
  assertNotCallingCallbacks();
  Log.d(TAG, "begin: ");
  stateVerifier.throwIfRecycled();
  startTime = LogTime.getLogTime();
  //1. 如果model为null,则调用onLoadFailed
  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.
  //如果已经完成,则调用onResourceReady
  if (status == Status.COMPLETE) {
    Log.d(TAG, "begin: resource"+resource);
    onResourceReady(resource, DataSource.MEMORY_CACHE);
    return;
  }

  // Restarts for requests that are neither complete nor running can be treated as new requests
  // and can run again from the beginning.
  //等待尺寸
  status = Status.WAITING_FOR_SIZE;
  //如果设置了overrideWidth和overrideHeight,则调用onSizeReady
  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));
  }
}

获取图片宽高

TargetgetSize方法在ViewTarget中实现。ViewTargetgetSize方法会调用SizeDeterminergetSize方法。SizeDeterminerViewTarget的静态内部类。

1
2
3
4
//ViewTarget getSize方法
public void getSize(@NonNull SizeReadyCallback cb) {
    sizeDeterminer.getSize(cb);
}

SizeDeterminergetSize方法获取完成后,会调用SizeReadyCallbackonSizeReady方法。SingleRequest实现了SizeReadyCallback接口,会调用SingleRequestonSizeReady方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//SizeDeterminer getSize方法
void getSize(@NonNull SizeReadyCallback cb) {
    int currentWidth = getTargetWidth(); //获取宽
    int currentHeight = getTargetHeight(); //获取高
    if (isViewStateAndSizeValid(currentWidth, currentHeight)) {
        cb.onSizeReady(currentWidth, currentHeight);
        return;
    }

    // We want to notify callbacks in the order they were added and we only expect one or two
    // callbacks to be added a time, so a List is a reasonable choice.
    if (!cbs.contains(cb)) {
        cbs.add(cb);
    }
    //如果获取为null 添加OnPreDrawListener,当回调时,再次获取宽高
    if (layoutListener == null) {
        ViewTreeObserver observer = view.getViewTreeObserver();
        layoutListener = new SizeDeterminerLayoutListener(this);
        observer.addOnPreDrawListener(layoutListener);
    }
}
1
2
3
4
5
6
private int getTargetHeight() {
  int verticalPadding = view.getPaddingTop() + view.getPaddingBottom();
  LayoutParams layoutParams = view.getLayoutParams();
  int layoutParamSize = layoutParams != null ? layoutParams.height : PENDING_SIZE;
  return getTargetDimen(view.getHeight(), layoutParamSize, verticalPadding);
}

如果overrideWidthoverrideHeight设置为SIZE_ORIGINAL,则为图片的真实大小。

1
2
3
4
5
6
7
8
//Downsampler decodeFromWrappedStreams方法
//获取图片的原始宽高
int[] sourceDimensions = getDimensions(is, options, callbacks, bitmapPool);
int sourceWidth = sourceDimensions[0];
int sourceHeight = sourceDimensions[1];
//如果设置Target.SIZE_ORIGINAL 则为原始宽高
int targetWidth = requestedWidth == Target.SIZE_ORIGINAL ? sourceWidth : requestedWidth;
int targetHeight = requestedHeight == Target.SIZE_ORIGINAL ? sourceHeight : requestedHeight;

onSizeReady

onSizeReady会调用Engineload方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public synchronized void onSizeReady(int width, int height) {
  stateVerifier.throwIfRecycled();
  if (IS_VERBOSE_LOGGABLE) {
    logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
  }
  if (status != Status.WAITING_FOR_SIZE) {
    return;
  }
  status = Status.RUNNING;

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

  if (IS_VERBOSE_LOGGABLE) {
    logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
  }
  Log.d(TAG,"onSizeReady "+requestOptions.getResourceClass()+",width="+width+",height="+height);
  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);

  // This is a hack that's only useful for testing right now where loads complete synchronously
  // even though under any executor running on any thread but the main thread, the load would
  // have completed asynchronously.
  if (status != Status.RUNNING) {
    loadStatus = null;
  }
  if (IS_VERBOSE_LOGGABLE) {
    logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
  }
}

Engline

EngineGlideBuilderbuild方法中创建。

构造函数

Engine的构造函数,负责初始化一些必要的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
@VisibleForTesting 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) {
  this.cache = cache; //内存缓存
  this.diskCacheProvider = new LazyDiskCacheProvider(diskCacheFactory);

  if (activeResources == null) {
    activeResources = new ActiveResources(isActiveResourceRetentionAllowed);
  }
  this.activeResources = activeResources;
  activeResources.setListener(this);

  if (keyFactory == null) {
    keyFactory = new EngineKeyFactory();
  }
  this.keyFactory = keyFactory;

  if (jobs == null) {
    jobs = new Jobs();
  }
  this.jobs = jobs;

  if (engineJobFactory == null) {
    engineJobFactory =
        new EngineJobFactory(
            diskCacheExecutor,
            sourceExecutor,
            sourceUnlimitedExecutor,
            animationExecutor,
            /*engineJobListener=*/ this,
            /*resourceListener=*/ this);
  }
  this.engineJobFactory = engineJobFactory;
  //默认为null 创建Factory
  if (decodeJobFactory == null) {
    decodeJobFactory = new DecodeJobFactory(diskCacheProvider);
  }
  this.decodeJobFactory = decodeJobFactory;

  if (resourceRecycler == null) {
    resourceRecycler = new ResourceRecycler();
  }
  this.resourceRecycler = resourceRecycler;

  cache.setResourceRemovedListener(this);
}

load

load方法会优先调用loadFromMemory从内存缓存中获取,如果内存缓存中不存在,则调用waitForExistingOrStartNewJob方法。loadFromMemory方法,这里先不做分析,在后面分析Glide的缓存的时候会单独分析。接下来我们直接分析waitForExistingOrStartNewJob方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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, //url
        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);
  }
}

waitForExistingOrStartNewJob

waitForExistingOrStartNewJob负责创建EngineJobDecodeJob,并且调用EngineJob.start方法执行DecodeJob。创建EngineJob的过程中,会优先从缓存中获取,如果缓存中存在直接返回。waitForExistingOrStartNewJob会返回一个LoadStatus,并最终返回给SingleRequestLoadStatus可以看做是EngineJob的代理类,SingleRequest可以通过调用cancle方法移除EngineJob的回调。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/等待存在的job或者开启一个新的job
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);
    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);
  Log.d(TAG, " waitForExistingOrStartNewJob resourceClass =" + resourceClass);
  //创建decodeJob
  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);

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

EngineJob

EngineJob创建过程

EngineJob通过Engine的静态内部类EngineJobFactory构建的。EngineJobFactory会先调用EngineJob的构造函数,然后调用EngineJobinit方法进行初始化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
static class EngineJobFactory {
  @Synthetic final Pools.Pool<EngineJob<?>> pool =
  FactoryPools.threadSafe(
      JOB_POOL_SIZE, //缓存池大小
      new FactoryPools.Factory<EngineJob<?>>() {
        @Override
        public EngineJob<?> create() {
          return new EngineJob<>(
              diskCacheExecutor,
              sourceExecutor,
              sourceUnlimitedExecutor,
              animationExecutor,
              engineJobListener,
              resourceListener,
              pool);
        }
      });

  @SuppressWarnings("unchecked") <R> EngineJob<R> build(
    Key key,
    boolean isMemoryCacheable,
    boolean useUnlimitedSourceGeneratorPool,
    boolean useAnimationPool,
    boolean onlyRetrieveFromCache) {
  EngineJob<R> result = Preconditions.checkNotNull((EngineJob<R>) pool.acquire());
  return result.init(
      key,
      isMemoryCacheable,
      useUnlimitedSourceGeneratorPool,
      useAnimationPool,
      onlyRetrieveFromCache);
  }
}

start

EngineJobstart方法会调用GlideExecutor执行DecodeJob

1
2
3
4
5
6
public synchronized void start(DecodeJob<R> decodeJob) {
  this.decodeJob = decodeJob;
  GlideExecutor executor =
      decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
  executor.execute(decodeJob);
}

DecodeJob

DecodeJob创建过程

DecodeJob通过Engine的静态内部类DecodeJobFactory构建的。DecodeJobFactory会先调用DecodeJob的构造函数,然后调用DecodeJobinit方法进行初始化。

DecodeJob实现了Runnable方法,EngineJobstart方法会调用DecodeJobrun方法。 run方法将调用runWrapped方法。

runWrapped

runWrapped方法会先获取下一个阶段,并调用runGenerators方法运行Generator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

DecodeJob的工作过程会经历以下6个阶段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private enum Stage {
  /**
   * The initial stage.
   */
  INITIALIZE,
  /**
   * Decode from a cached resource.
   */
  RESOURCE_CACHE,
  /**
   * Decode from cached source data.
   */
  DATA_CACHE,
  /**
   * Decode from retrieved source.
   */
  SOURCE,
  /**
   * Encoding transformed resources after a successful load.
   */
  ENCODE,
  /**
   * No more viable stages.
   */
  FINISHED,
}

getNextStage方法负责根据当前阶段来获取下一个符合条件的阶段。这里我们以第一次加载网络图片为例,分析该过程。当我们第一次调用getNextStage,并且diskCacheStrategydecodeCachedResource()返回true,那么将进入RESOURCE_CACHE阶段。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private Stage getNextStage(Stage current) {
  switch (current) {
    case INITIALIZE:
      return diskCacheStrategy.decodeCachedResource()
          ? Stage.RESOURCE_CACHE
          : getNextStage(Stage.RESOURCE_CACHE);
    case RESOURCE_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.
      return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
    case SOURCE:
    case FINISHED:
      return Stage.FINISHED;
    default:
      throw new IllegalArgumentException("Unrecognized stage: " + current);
  }
}

getNextGenerator

getNextGenerator负责根据不同的Stage获取不同的Generator。当前阶段为RESOURCE_CACHE时,将返回ResourceGenerator。接着runWrapped方法会调用runGenerators方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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);
  }
}

runGenerators

runGenerators方法会调用当前GeneratorstarNext方法。当前的GeneratorResourceCacheGenerator。所以这里调用的是ResourceCacheGeneratorstarNext方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
    }
  }
  // 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.
}

DataFetcherGeneratorDataFetcher生成器。

ResourceCacheGenerator

ResourceCacheGenerator负责从缓存中获取资源缓存,如果没有缓存,则返回false。第一次加载图片时,不存在缓存,所以返回false。再回到runGenerators方法中,当返回false,会再次调用getNextStage获取下一个阶段,下一个GeneratorDataCacheGenerator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
public boolean startNext() {
  Log.d(TAG,"startNext");
  List<Key> sourceIds = helper.getCacheKeys();
  if (sourceIds.isEmpty()) {
    return false;
  }
  List<Class<?>> resourceClasses = helper.getRegisteredResourceClasses();
  if (resourceClasses.isEmpty()) {
    if (File.class.equals(helper.getTranscodeClass())) {
      return false;
    }
    throw new IllegalStateException(
        "Failed to find any load path from "
            + helper.getModelClass()
            + " to "
            + helper.getTranscodeClass());
  }
  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.
    currentKey =
        new ResourceCacheKey( // NOPMD AvoidInstantiatingObjectsInLoops
            helper.getArrayPool(),
            sourceId,
            helper.getSignature(),
            helper.getWidth(),
            helper.getHeight(),
            transformation,
            resourceClass,
            helper.getOptions());
    //获取缓存文件
    cacheFile = helper.getDiskCache().get(currentKey);
    if (cacheFile != null) {
      Log.d(TAG,"cacheFile"+cacheFile.getAbsolutePath());
      sourceKey = sourceId;
      modelLoaders = helper.getModelLoaders(cacheFile); //获取对应的modelLoaders
      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;
}

DataCacheGenerator

DataCacheGenerator负责从缓存中获取数据缓存,如果没有缓存,则返回false。第一次加载图片时,不存在缓存,所以返回false。再回到runGenerators方法中,当返回false,会再次调用getNextStage获取下一个阶段,下一个GeneratorSourceGenerator

1
2
3
4
5
6
7
8
9
10
11
//构造函数 调用DecodeHelper的getCacheKeys
DataCacheGenerator(DecodeHelper<?> helper, FetcherReadyCallback cb) {
  this(helper.getCacheKeys(), helper, cb);
}
// In some cases we may want to load a specific cache key (when loading from source written to
// cache), so we accept a list of keys rather than just obtain the list from the helper.
DataCacheGenerator(List<Key> cacheKeys, DecodeHelper<?> helper, FetcherReadyCallback cb) {
  this.cacheKeys = cacheKeys;
  this.helper = helper;
  this.cb = cb;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@Override
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;
  Log.d(TAG, "modelLoaders = " + modelLoaders);
  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())) {
      Log.d(TAG, "startNext: " + modelLoader.getClass());
      started = true;
      loadData.fetcher.loadData(helper.getPriority(), this);
    }
  }
  return started;
}

SourceGenerator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public boolean startNext() {
    Log.d(TAG, "startNext: " + dataToCache);
    //如果dataToCache不为空 则缓存数据,第一次调用为空
    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;
            Log.d(TAG, "startNext loadData=" + loadData.fetcher.getClass().getSimpleName());
            loadData.fetcher.loadData(helper.getPriority(), this);
        }
    }
    return started;
}

图片获取成功之后会调用onDataReady方法。onDataReady方法调用FetcherReadyCallbackreschedule。最终通过回调会调用EngineJobreschedule方法,再次调用DecodeJobrun方法。然后再次调用SourceGeneratorstartNext方法。此时dataToCache不为空,则缓存数据,然后调用DataCacheGeneratorstartNext获取缓存的数据。DataCacheGenerator获取完成数据会调用onDataFetcherReady方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Override
public void onDataReady(Object data) {
    Log.d(TAG, "onDataReady: ");
    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);
    }
}
1
2
3
4
5
6
7
@Override
public void reschedule(DecodeJob<?> job) {
  Log.d(TAG,"reschedule: ");
  // Even if the job is cancelled here, it still needs to be scheduled so that it can clean itself
  // up.
  getActiveSourceExecutor().execute(job);
}

ModelLoader

ModelLoader是一个工厂接口,负责将复杂的数据类型转换为具体的数据类型,DataFetcher使用该具体类型获取数据。

getLoadData()

DecodeHelpergetLoadData方法会首先调用RegistrygetModelLoaders方法,来获取符合条件的ModelLoader。然后遍历所有ModelLoader,并调用ModelLoaderbuildLoadData方法,过滤掉空的LoadData

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//DecodeHelper
List<LoadData<?>> getLoadData() {
  if (!isLoadDataSet) {
    isLoadDataSet = true; //获取成功之后设置为true 避免多次获取
    loadData.clear();
    //根据Model获取ModelLoader
    List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
    //noinspection ForLoopReplaceableByForEach to improve perf
    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;
}

getModelLoaders()

1
2
3
4
5
6
//Registry
@NonNull
public <Model> List<ModelLoader<Model, ?>> getModelLoaders(@NonNull Model model) {
  //调用ModelLoaderRegistry的getModelLoaders
  return modelLoaderRegistry.getModelLoaders(model);
}

ModelLoaderRegistrygetModelLoaders方法会调用ModelLoaderRegistrygetModelLoadersForClass方法。getModelLoadersForClass方法会先从缓存中获取对应的ModelLoader,如果获取不到,则调用MultiModelLoaderFactorybuild方法。获取完成之后,调用ModelLoaderhandles方法筛选符合条件的ModelLoader

比如输入的model是一个http链接。符合条件的ModelLoader有4个。但是DataUrlLoaderhandles返回false所以过滤掉只剩下三个。

image-20210722155844793

1
2
3
4
5
6
7
8
9
//DataUrlLoader
private static final String DATA_SCHEME_IMAGE = "data:image";
@Override
public boolean handles(@NonNull Model model) {
  // We expect Model to be a Uri or a String, both of which implement toString() efficiently. We
  // should reconsider this implementation before adding any new Model types.
  return model.toString()
      .startsWith(DATA_SCHEME_IMAGE);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//ModelLoaderRegistry
@NonNull
public <A> List<ModelLoader<A, ?>> getModelLoaders(@NonNull A model) {
  List<ModelLoader<A, ?>> modelLoaders = getModelLoadersForClass(getClass(model));
  if (modelLoaders.isEmpty()) {
    throw new NoModelLoaderAvailableException(model);
  }
  int size = modelLoaders.size();
  boolean isEmpty = true;
  List<ModelLoader<A, ?>> filteredLoaders = Collections.emptyList();
  //noinspection ForLoopReplaceableByForEach to improve perf
  for (int i = 0; i < size; i++) {
    ModelLoader<A, ?> loader = modelLoaders.get(i);
    if (loader.handles(model)) {
      if (isEmpty) {
        filteredLoaders = new ArrayList<>(size - i);
        isEmpty = false;
      }
        //根据ModelLoader的handles方法,过滤掉不匹配的
      //假设传入的是url,则过滤掉DataUrlLoader
      filteredLoaders.add(loader);
    }
  }
  if (filteredLoaders.isEmpty()) {
    throw new NoModelLoaderAvailableException(model, modelLoaders);
  }
  return filteredLoaders;
}
1
2
3
4
5
6
7
8
9
10
11
12
@NonNull
private synchronized <A> List<ModelLoader<A, ?>> getModelLoadersForClass(
    @NonNull Class<A> modelClass) {
  //从缓存中取
  List<ModelLoader<A, ?>> loaders = cache.get(modelClass);
  if (loaders == null) {
    //调用MultiModelLoaderFactory的build方法
    loaders = Collections.unmodifiableList(multiModelLoaderFactory.build(modelClass));
    cache.put(modelClass, loaders);
  }
  return loaders;
}

假设这里的modelhttp链接,获得的entry的Factory为StringLoader.StreamFactory。这里获取符合条件的为4个,这里只举例一个,其他都差不多。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@NonNull
synchronized <Model> List<ModelLoader<Model, ?>> build(@NonNull Class<Model> modelClass) {
  try {
    List<ModelLoader<Model, ?>> loaders = new ArrayList<>();
    for (Entry<?, ?> entry : entries) {
      // Avoid stack overflow recursively creating model loaders by only creating loaders in
      // recursive requests if they haven't been created earlier in the chain. For example:
      // A Uri loader may translate to another model, which in turn may translate back to a Uri.
      // The original Uri loader won't be provided to the intermediate model loader, although
      // other Uri loaders will be.
      if (alreadyUsedEntries.contains(entry)) {
        continue;
      }
      //根据ModelClass进行判断
      if (entry.handles(modelClass)) {
        alreadyUsedEntries.add(entry);
        //调用Factory创建Loader
        loaders.add(this.<Model, Object>build(entry));
        alreadyUsedEntries.remove(entry);
      }
    }
    return loaders;
  } catch (Throwable t) {
    alreadyUsedEntries.clear();
    throw t;
  }
}
1
2
3
private <Model, Data> ModelLoader<Model, Data> build(@NonNull Entry<?, ?> entry) {
  return (ModelLoader<Model, Data>) Preconditions.checkNotNull(entry.factory.build(this));
}

StringLoader.StreamFactorybuild方法会调用MultiModelLoaderFactorybuild方法,寻找Model为Uri的ModelLoader

1
2
3
4
5
6
7
8
9
10
11
12
13
public static class StreamFactory implements ModelLoaderFactory<String, InputStream> {

    @NonNull
    @Override
    public ModelLoader<String, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) {
      return new StringLoader<>(multiFactory.build(Uri.class, InputStream.class));
    }

    @Override
    public void teardown() {
      // Do nothing.
    }
}

如果存在多个ModelLoader方法,就会返回一个MultiModelLoader对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
@NonNull
public synchronized <Model, Data> ModelLoader<Model, Data> build(
    @NonNull Class<Model> modelClass, @NonNull Class<Data> dataClass) {
  try {
    List<ModelLoader<Model, Data>> loaders = new ArrayList<>();
    boolean ignoredAnyEntries = false;
    for (Entry<?, ?> entry : entries) {
      // Avoid stack overflow recursively creating model loaders by only creating loaders in
      // recursive requests if they haven't been created earlier in the chain. For example:
      // A Uri loader may translate to another model, which in turn may translate back to a Uri.
      // The original Uri loader won't be provided to the intermediate model loader, although
      // other Uri loaders will be.
      if (alreadyUsedEntries.contains(entry)) {
        ignoredAnyEntries = true;
        continue;
      }
      if (entry.handles(modelClass, dataClass)) {
        alreadyUsedEntries.add(entry);
        loaders.add(this.<Model, Data>build(entry));
        alreadyUsedEntries.remove(entry);
      }
    }
    //如果存在多个就构建成一个MultiModelLoader
    if (loaders.size() > 1) {
      return factory.build(loaders, throwableListPool);
    } else if (loaders.size() == 1) {
      return loaders.get(0);
    } else {
      // Avoid crashing if recursion results in no loaders available. The assertion is supposed to
      // catch completely unhandled types, recursion may mean a subtype isn't handled somewhere
      // down the stack, which is often ok.
      if (ignoredAnyEntries) {
        return emptyModelLoader();
      } else {
        throw new NoModelLoaderAvailableException(modelClass, dataClass);
      }
    }
  } catch (Throwable t) {
    alreadyUsedEntries.clear();
    throw t;
  }
}
1
2
3
4
5
6
7
8
static class Factory {
  @NonNull
  public <Model, Data> MultiModelLoader<Model, Data> build(
      @NonNull List<ModelLoader<Model, Data>> modelLoaders,
      @NonNull Pool<List<Throwable>> throwableListPool) {
    return new MultiModelLoader<>(modelLoaders, throwableListPool);
  }
}

ModelLoader获取完成之后,DecodeHelpergetLoadData方法会调用ModelLoaderbuildLoadData方法。还以Model为Http链接为例。会依次调用StringLoaderMultiModelLoaderHttpUriLoaderHttpGlideUrlLoader

This post is licensed under CC BY 4.0 by the author.