Glide源码解析四——Engine相关(从数据源获取数据)

Engine

Glide源码分析二——Request相关可知,SingleRequest#onSizeReady(w,h)可知是通过Engine来加载图片的。

Engine是在GlideBuilder#build(context)构造Glide时,new出来传给Glide的。之后在RequestBuilder创建SingleRequest时通过GlideContext.getEngine()获取Engine并传给SingleRequest.

GlideBuilder.java
Glide build(@NonNull Context context) {
    
    ...
    if (engine == null) {
      engine =
          new Engine(
              memoryCache,  // 内存缓存
              diskCacheFactory, // 磁盘缓存工厂类
              diskCacheExecutor,
              sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor(),
              animationExecutor,
              isActiveResourceRetentionAllowed);
    }
    ...
    return new Glide(
        ...
        engine,
        ...);
}
public class Engine
    implements EngineJobListener,
        MemoryCache.ResourceRemovedListener,
        EngineResource.ResourceListener {

    private final Jobs jobs;
    private final EngineKeyFactory keyFactory;
    private final MemoryCache cache;
    private final EngineJobFactory engineJobFactory;
    private final ResourceRecycler resourceRecycler;
    private final LazyDiskCacheProvider diskCacheProvider;
    private final DecodeJobFactory decodeJobFactory;
    private final ActiveResources activeResources;
    
    
    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;
        
        // 三级磁盘缓存的Provider
        this.diskCacheProvider = new LazyDiskCacheProvider(diskCacheFactory);

        // 一级内存缓存
        if (activeResources == null) {
          activeResources = new ActiveResources(isActiveResourceRetentionAllowed);
        }
        this.activeResources = activeResources;
        activeResources.setListener(this);

        // 默认的KeyFactory
        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;

        if (decodeJobFactory == null) {
          decodeJobFactory = new DecodeJobFactory(diskCacheProvider);
        }
        this.decodeJobFactory = decodeJobFactory;

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

        cache.setResourceRemovedListener(this);
    }
    
    
    
    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、2级缓存中取出资源
          memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);

          if (memoryResource == null) {
            
            // 如果没有内存缓存,则创建EngineJob
            return waitForExistingOrStartNewJob(
                glideContext,
                model,
                signature,
                width,
                height,
                resourceClass,
                transcodeClass,
                priority,
                diskCacheStrategy,
                transformations,
                isTransformationRequired,
                isScaleOnlyOrNoTransform,
                options,
                isMemoryCacheable, // 从BaseRequestOptions中取,默认是true,除非调用了skipMemoryCache(true)
                useUnlimitedSourceExecutorPool,
                useAnimationPool,
                onlyRetrieveFromCache, // 从BaseRequestOptions中取,默认是false
                cb,
                callbackExecutor, // RequestBuilder#into(...)不传就是在主线程
                key,
                startTime);
          }
        }

        // 如果有内存缓存则通过回调ResourceCallback#onResourceReady(...)通知SingleRequest资源加载完成,进而通知target加载资源
        cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
        return null;
    }
    
    // 从1、2级缓存中取出资源,关于1、2级缓存可以参考MemoryCache、ActiveResource章节
    private EngineResource<?> loadFromMemory(
      EngineKey key, boolean isMemoryCacheable, long startTime) {
        if (!isMemoryCacheable) {
          return null;
        }

        // 先从一级缓存中取
        EngineResource<?> active = loadFromActiveResources(key);
        if (active != null) {
          return active;
        }
        
        
        // 一级缓存中没有则尝试从二级缓存中取
        EngineResource<?> cached = loadFromCache(key);
        if (cached != null) {
          return cached;
        }

        return null;
    }
    
    // 从一级缓存中取资源
    private EngineResource<?> loadFromActiveResources(Key key) {
        EngineResource<?> active = activeResources.get(key);
        if (active != null) {
          // 将EngineResource的引用计数+1,当引用数为0时释放掉
          active.acquire();
        }

        return active;
    }
    
    // 从二级缓存中取资源
    private EngineResource<?> loadFromCache(Key key) {
        EngineResource<?> cached = getEngineResourceFromCache(key);
        if (cached != null) {
          // 将EngineResource的引用计数+1,当引用数为0时释放掉
          cached.acquire();
          // 从二级缓存中取到资源后放入一级缓存
          activeResources.activate(key, cached);
        }
        return cached;
    }
    
    private EngineResource<?> getEngineResourceFromCache(Key key) {
    
        // 从MemoryCache中取出Resource的同时,也将其从MemoryCache中移除,等到Resource引用数为0时,会再放入MemoryCache
        Resource<?> cached = cache.remove(key);

        final EngineResource<?> result;
        if (cached == null) {
          result = null;
        } else if (cached instanceof EngineResource) {
          // Resource有很多子类,如果是EngineResource则直接返回
          result = (EngineResource<?>) cached;
        } else {
          // 如果不是EngineResource,则包装成EngineResource
          result =
              new EngineResource<>(
                  cached, /*isMemoryCacheable=*/ true, /*isRecyclable=*/ true, key, /*listener=*/ this);
        }
        return result;
    }
    
    
    
    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) {
        
        // 如果当前key已经有对应EngineJob了,则将ResourceCallback和Executor添加到该EngineJob上
        EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
        if (current != null) {
          current.addCallback(cb, callbackExecutor);
          return new LoadStatus(cb, current);
        }

        // 从EngineJobFactory中获取EngineJob,内部有对象池可复用EngineJob
        EngineJob<R> engineJob =
            engineJobFactory.build(
                key,
                isMemoryCacheable,
                useUnlimitedSourceExecutorPool,
                useAnimationPool,
                onlyRetrieveFromCache);
        // 和EngineJobFactory一样,内部有对象池
        DecodeJob<R> decodeJob =
            decodeJobFactory.build(
                glideContext,
                model,
                key,
                signature,
                width,
                height,
                resourceClass,
                transcodeClass,
                priority,
                diskCacheStrategy,
                transformations,
                isTransformationRequired,
                isScaleOnlyOrNoTransform,
                onlyRetrieveFromCache,
                options,
                engineJob);
        
        // 将EngineJob放入Jobs中
        jobs.put(key, engineJob);

        // 将ResourceCallback和Executor添加到该EngineJob上
        engineJob.addCallback(cb, callbackExecutor);
        
        // 启动EngineJob
        engineJob.start(decodeJob);

        return new LoadStatus(cb, engineJob);
    }
}
  1. Resource<Z>包含着真正的资源,例如Bitmap、Drawable、File等,提供了获取资源、资源类class、资源大小、回收资源的方法。
  2. EngineResource是Resource<Z>的包装类,内部包含引用计数acquire,每次被使用acquire()都会+1,每次被释放release()都会-1,当acquire==0时,会回调通知Engine,从ActiveResources中移除,如果可缓存在内存中则放入MemoryCache,否则回收recycle()。
  3. DecodeJob是个Runnable,用于从磁盘(SDCard)获取处理后的资源(ResourceCache)、原始资源(ResourceData)、以及从数据源(Source)获取数据。
  4. EngineJob相当于是管理者,用于管理、监听DecodeJob的执行,当资源加载完成后,会保存资源并通过EngineJobListener#onEngineJobComplete(EngineJob, Key, engineResource)通知Engine。
// EngineResource.java
class EngineResource<Z> implements Resource<Z> {

  // 是否可缓存在内存中
  private final boolean isMemoryCacheable;
  
  // 被包装的资源
  private final Resource<Z> resource;
    
  // 引用计数
  private int acquired;

  // 资源释放回调
  interface ResourceListener {
    void onResourceReleased(Key key, EngineResource<?> resource);
  }
  
  // 回收资源
  @Override
  public synchronized void recycle() {
    // ... 省略部分代码
    resource.recycle();
  }
  
  // 引用资源
  synchronized void acquire() {
    // ... 省略部分代码
    ++acquired;
  }
  
  // 释放资源
  void release() {
    boolean release = false;
    synchronized (this) {
      // ... 省略部分代码
      
      // 如果引用计数为0,则释放资源
      if (--acquired == 0) {
        release = true;
      }
    }
    if (release) {
      // 回调通知Engine,将资源从ActiveResources中移除,如果资源可缓存在内存中,则放入MemoryCache,否则调用resource#recycle()回收资源
      listener.onResourceReleased(key, this);
    }
  }
}
加载资源流程图.png
资源释放后缓存流程图.png

EngineJob

class EngineJob<R> implements DecodeJob.Callback<R>, Poolable {

  public synchronized void start(DecodeJob<R> decodeJob) {
    this.decodeJob = decodeJob;
    GlideExecutor executor =
        decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
    // 使用线程池执行Runnable,decodeJob是个Runnable
    executor.execute(decodeJob);
  }
  
  synchronized void addCallback(final ResourceCallback cb, Executor callbackExecutor) {
    
    // 添加ResourceCallback和Executor
    cbs.add(cb, callbackExecutor);
    
    
    if (hasResource) {
      // 如果资源已经加载好了,则直接调用ResourceCallback#onResourceReady(engineResource, dataSource)通知SingleRequest
      incrementPendingCallbacks(1);
      callbackExecutor.execute(new CallResourceReady(cb));
    } else if (hasLoadFailed) {
      // 如果资源已经加载失败了,则通过调用ResourceCallback#onLoadFailed(exception)通知SingleRequest
      incrementPendingCallbacks(1);
      callbackExecutor.execute(new CallLoadFailed(cb));
    } else {
      Preconditions.checkArgument(!isCancelled, "Cannot add callbacks to a cancelled EngineJob");
    }
  }
  
  // 资源加载完成后,EngineJob保存资源,并通过回调通知Engine和SingleRequest
  @Override
  public void onResourceReady(Resource<R> resource, DataSource dataSource) {
    synchronized (this) {
      this.resource = resource;
      this.dataSource = dataSource;
    }
    notifyCallbacksOfResult();
  }
  
  void notifyCallbacksOfResult() {
    ResourceCallbacksAndExecutors copy;
    Key localKey;
    EngineResource<?> localResource;
    synchronized (this) {
      stateVerifier.throwIfRecycled();
      if (isCancelled) {
        // 如果已经取消了,则回收资源并释放EngineJob
        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");
      }
      
      // 通过factory创建EngineResource,包装resource
      engineResource = engineResourceFactory.build(resource, isCacheable, key, resourceListener);
      // 设置标志标识已经加载了资源
      hasResource = true;
      copy = cbs.copy();
      incrementPendingCallbacks(copy.size() + 1);

      localKey = key;
      localResource = engineResource;
    }

    // 通知Engine EngineJob已经执行完毕
    engineJobListener.onEngineJobComplete(this, localKey, localResource);
    
    // 通知SingleRequest资源加载完毕
    for (final ResourceCallbackAndExecutor entry : copy) {
      entry.executor.execute(new CallResourceReady(entry.cb));
    }
    decrementPendingCallbacks();
  }
  
  // onLoadFailed(GlideException e)和onResourceReady(...)类似,省略
  
  @Override
  public void reschedule(DecodeJob<?> job) {
    // 在Glide的线程池中重新执行DecodeJob,原因见DecodeJob#reschedule()和DecodeJob#onDataFetcherReady(...)
    getActiveSourceExecutor().execute(job);
  }

}

DecodeJob

class DecodeJob<R>
    implements DataFetcherGenerator.FetcherReadyCallback,
        Runnable,
        Comparable<DecodeJob<?>>,
        Poolable {
        
  private Callback<R> callback; // EngineJob的实例

  // 延时缓存数据管理类,内含Encoder和待缓存数据
  private final DeferredEncodeManager<?> deferredEncodeManager = new DeferredEncodeManager<>();

    
  public void run() {
    DataFetcher<?> localFetcher = currentFetcher;
    try {
      ...
      // 根据不同的状态获取不同的DataFetcherGenerator,执行不同的数据加载策略
      runWrapped();
    } catch (CallbackException e) {
      throw e;
    } catch (Throwable t) {
      ...
      throw t;
    } finally {
      // 调用上次加载数据的DataFetcher#cleanup()做一些清除资源的工作,例如HttpUrlFetcher会关闭输入流和连接
      if (localFetcher != null) {
        localFetcher.cleanup();
      }
      GlideTrace.endSection();
    }
  }
  
  // 根据不同的状态获取不同的DataFetcherGenerator,执行不同的数据加载策略
  private void runWrapped() {
    // DecodeJob在Engine#load(...)中,使用工厂类DecodeJobFactory.build(...)创建时被赋值为INITIALIZE
    switch (runReason) {
      case INITIALIZE:
        //
        stage = getNextStage(Stage.INITIALIZE);
        currentGenerator = getNextGenerator();
        runGenerators();
        break;
      case SWITCH_TO_SOURCE_SERVICE:
        // 如果是从数据源Source获取数据,例如通过SourceGenerator,则会执行rechedule(),此时runReason会置为SWITCH_TO_SOURCE_SERVICE,且currentGenerator还是上次的Generator,应该是SourceGenerator,调用其startNext()会去保存上次获取到的数据,并通过DataCacheGenerator获取待加载数据,详见DataFetcherGenerator章节
        runGenerators();
        break;
      case DECODE_DATA:
        decodeFromRetrievedData();
        break;
      default:
        throw new IllegalStateException("Unrecognized run reason: " + runReason);
    }
  }
  
  // 获取下一个状态
  private Stage getNextStage(Stage current) {
    switch (current) {
      case INITIALIZE:
        // 如果可以取磁盘缓存中存储的Resource资源(原始资源处理后的),则返回State.RESOURCE_CACHE,否则返回State.RESOURCE_CACHE的下个状态
        return diskCacheStrategy.decodeCachedResource()
            ? Stage.RESOURCE_CACHE
            : getNextStage(Stage.RESOURCE_CACHE);
      case RESOURCE_CACHE:
        // 如果可以取磁盘缓存中存储的原始资源的话,则返回State.DATA_CACHE,否则返回State.DATA_CACHE的下个状态
        return diskCacheStrategy.decodeCachedData()
            ? Stage.DATA_CACHE
            : getNextStage(Stage.DATA_CACHE);
      case DATA_CACHE:
        // 是否只能从内存中获取资源,是的话则返回结束状态State.FINISHED,否则返回数据源状态State.SOURCE
        return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
      case SOURCE:
      case FINISHED:
        return Stage.FINISHED;
      default:
        throw new IllegalArgumentException("Unrecognized stage: " + current);
    }
  }
  
  // 根据不同的状态获取对应的DataFetcherGenerator
  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);
  }
  
  // 执行Generator#startNext()加载数据,如果返回false说明获取数据失败,则取下个状态的Generator获取数据
  private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    while (!isCancelled
        && currentGenerator != null
        && !(isStarted = currentGenerator.startNext())) {
        
      // 加载失败的话,切换到下一状态和Generator
      stage = getNextStage(stage);
      currentGenerator = getNextGenerator();

      // 如果下个状态时SOURCE的话,则修改runReason为RunReason.SWITCH_TO_SOURCE_SERVICE,并回调到EngineJob中,在线程池中重新执行DecodeJob来获取数据
      if (stage == Stage.SOURCE) {
        reschedule();
        return;
      }
    }
    
    // 如果所有的状态都尝试了,即所有的Generator都执行了,仍然没有获取到数据,则算作加载失败
    if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
      notifyFailed();
    }
  }
  
  // 修改runReason为RunReason.SWITCH_TO_SOURCE_SERVICE,回调到EngineJob中,在Glide线程池中重新执行DecodeJob来加载数据。一般是从数据源Source获取数据时,例如通过SourceGenerator,会执行该方法。当DecodeJob重新执行时,currentGengerator还是上次的generator,一般是SourceGenerator,调用其startNext()会去保存上次获取到的数据,并通过DataCacheGenerator获取待加载数据,详见DataFetcherGenerator章节
  public void reschedule() {
    runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
    
    // 回调到EngineJob中,在Glide线程池中重新执行DecodeJob来加载数据
    callback.reschedule(this);
  }
  
  // Generator请求数据成功回调
  public void onDataFetcherReady(
      Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) {
    
    // 保存得到的数据、以及对应的key、DataFetcher等
    this.currentSourceKey = sourceKey;
    this.currentData = data;
    this.currentFetcher = fetcher;
    this.currentDataSource = dataSource;
    this.currentAttemptingKey = attemptedKey;
    
    // 如果当前线程不是请求数据时的线程,则回调到EngineJob中切换到Glide线程池中,之后再执行该DecodeJob来完成Decode Data操作
    if (Thread.currentThread() != currentThread) {
      runReason = RunReason.DECODE_DATA;
      callback.reschedule(this);
    } else {
      // 将请求得到的数据解码成最终结果(transcode类型)并包装成Resource对象
      decodeFromRetrievedData();
    }
  }
  
  // 将请求得到的数据解码成最终结果(transcode类型)并包装成Resource对象
  private void decodeFromRetrievedData() {
    
    // 解码,这里得到的是最终结果(transcode类型)的包装类Resource
    Resource<R> resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    
    if (resource != null) {
      
      // 解码成功则准备缓存数据
      notifyEncodeAndRelease(resource, currentDataSource);
    } else {
    
      // 如果解码得到的Resource为null,则重新执行Generator,获取下一个ModelLoader来尝试获取数据(ps:Generator中可能会有多个能够处理model的ModelLoader)
      runGenerators();
    }
  }
  
  // 通知EngineJob数据请求完成、如果有待缓存的数据(已解码完成)则执行缓存,并尝试释放资源
  private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
    ...

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

    // 通知EngineJob数据请求完成
    callback.onResourceReady(result, dataSource);

    stage = Stage.ENCODE;
    try {
      
      // 如果Decoder解码成功,会在onResourceDecoded(DataSource, Resource<Z>)中调用deferredEncodeManager#init(...)保存解码和变换后的数据以及对应的Key和ResourceEncoder,然后在这里进行缓存
      if (deferredEncodeManager.hasResourceToEncode()) {
        deferredEncodeManager.encode(diskCacheProvider, options);
      }
    } finally {
      if (lockedResource != null) {
        lockedResource.unlock();
      }
    }
    
    // 尝试释放资源
    onEncodeComplete();
  }
  
  // 解码,这里返回的是最终结果(transcode类型)的包装类Resource
  private <Data> Resource<R> decodeFromData(
      DataFetcher<?> fetcher, Data data, DataSource dataSource) throws GlideException {
    try {
      if (data == null) {
        // fetcher没有请求到数据
        return null;
      }
      
      // 获取dataClass的LoadPath,使用其中的Decoder和Transcoder进行解码操作
      Resource<R> result = decodeFromFetcher(data, dataSource);
      return result;
    } finally {
      // 执行fetcher的清理工作
      fetcher.cleanup();
    }
  }
  
  // 获取dataClass的LoadPath,使用其中的Decoder和Transcoder进行解码操作
  private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource) {
  
    // 获取dataClass的LoadPath
    LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
    
    // 使用LoadPath的Decoder和Transcoder进行解码操作
    return runLoadPath(data, dataSource, path);
  }
  
  // 使用LoadPath的Decoder和Transcoder进行解码操作
  private <Data, ResourceType> Resource<R> runLoadPath(
      Data data, DataSource dataSource, LoadPath<Data, ResourceType, R> path) {
    ...
    // 获取Registry中注册的DataRewinder,负责将DataClass是Stream类型的数据重置到起始位置
    DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
    try {
      
      // 使用其中的DecodePath的Decoder和Transcoder进行解码操作,Decoder解码成功后会回调DecodeCallback#onResourceDecoded( Resource<Z> decoded),在该回调中会使用Transformation#transform(...)进行变换操作,之后会调用DeferredEncodeManager.init(...)将变换后的数据保存起来。最后在Transcoder解码完成后会在notifyEncodeAndRelease(...)中调用DeferredEncodeManager#encode(...)缓存变换后的数据TransformedClass。
      return path.load(
          rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
    } finally {
      rewinder.cleanup();
    }
  }
  
  
  // DecodePath的解码回调
  private final class DecodeCallback<Z> implements DecodePath.DecodeCallback<Z> {

    private final DataSource dataSource;

    @Synthetic
    DecodeCallback(DataSource dataSource) {
      this.dataSource = dataSource;
    }
    
    /**
     * @params decoded 是Decoder解码得到的数据
     * @return 变换后的数据
     */
    @Override
    public Resource<Z> onResourceDecoded(@NonNull Resource<Z> decoded) {
      return DecodeJob.this.onResourceDecoded(dataSource, decoded);
    }
  }
  
  /**
   * Decoder解码完成后触发该方法
   * @params decoded 是ResourceDecoder解码得到的数据DecodedClass
   * @return 变换后的数据TransformedClass
   */
  <Z> Resource<Z> onResourceDecoded(DataSource dataSource, Resource<Z> decoded) {
    
    Class<Z> resourceSubClass = (Class<Z>) decoded.get().getClass();
    Transformation<Z> appliedTransformation = null;
    Resource<Z> transformed = decoded;
    
    // 如果数据源不是处理后的数据,则利用Transformation#tranform(...)进行变换操作
    // 因为数据源可能是通过ResourceCacheGenerator获取的之前缓存的处理(变换)过的数据,这个数据是经过transform的,所以不需要再transform
    if (dataSource != DataSource.RESOURCE_DISK_CACHE) {
      appliedTransformation = decodeHelper.getTransformation(resourceSubClass);
      transformed = appliedTransformation.transform(glideContext, decoded, width, height);
    }
    
    ...

    // 如果Registry中有能够处理tranformed类型的ResourceEncoder,则获取ResourceEncoder和对应的EncodeStrategy,省略该部分代码...

    Resource<Z> result = transformed;
    
    // ... 省略根据encodeStrategy生成key的代码

    // 将key, encoder, 变换后的数据TransformedClass保存在DeferredEncodeManager中
    LockedResource<Z> lockedResult = LockedResource.obtain(transformed);
    deferredEncodeManager.init(key, encoder, lockedResult);
    result = lockedResult;
    return result;
  }
}

DocodeJob主要是根据不同的Stage获取不同的DataFetcherGenerator,不同的DataFetcherGenerator可以得到不同的DataFetcher,DataFetcher是用来请求数据的。

获取数据成功之后,会使用DecodePath中保存的Decoder、Transcoder进行解码操作,得到最终数据。

其中Decoder解码成功后会回调DecodeCallback#onResourceDecoded(Resource<Z> decoded),在该回调中会使用Transformation#transform(...)进行变换操作,之后会调用DeferredEncodeManager#init(...)将变换后的数据保存起来。 最后在Transcoder解码完成后会在notifyEncodeAndRelease(...)中调用DeferredEncodeManager#encode(...)缓存变换后的数据。

DataFetcherGenerator

DataFetcherGenerator有3个子类,逐级尝试获取数据:

  1. ResourceCacheGenerator,从磁盘缓存中获取原始资源处理后的Resource资源
  2. DataCacheGenerator,从磁盘缓存中获取原始资源
  3. SourceGenerator,从数据源(例如网络)中获取资源

这里分析下ResourceCacheGenerator吧:

// ResourceCacheGenerator.java

private Object model;

// 实例是LazyDiskCacheProvider,在Engine中设置给DecodeJobFactory,之后的传递路径是DecodeJobFactory -> DecodeJob -> DecodeHelper。实例是LazyDiskCacheProvider,内部包含一个DiskCache.Factory,实例是InternalCacheDiskCacheFactory,它的build()方法会创建DiskLruCacheWrapper,是一个DiskLruCache的包装类。
private DecodeJob.DiskCacheProvider diskCacheProvider;

// 当前缓存资源对应的key
private Key sourceKey;

// 资源请求回调
private final FetcherReadyCallback cb;

private final DecodeHelper<?> helper;

ResourceCacheGenerator(DecodeHelper<?> helper, FetcherReadyCallback cb) {
    this.helper = helper;
    this.cb = cb;
}

// 开始获取缓存,获取成功返回true,失败返回false
public boolean startNext() {
    // Registry在Engine中初始化后,添加了很多输入类型(ModelClass),输出类型(DataClass),以及对应的ModelLoaderFactory,并封装成Entry放入MultiModelLoaderFactory中。
    // 这里通过DecodeHelper获取能够处理model的Entry,并用Entry中的ModelLoaderFactory创建对应的ModelLoader,然后用ModelLoader创建LoadData,之后返回LoadData的sourceKey和alternateKeys
    List<Key> sourceIds = helper.getCacheKeys();
    if (sourceIds.isEmpty()) {
      return false;
    }
    
    // ...
    
    while (modelLoaders == null || !hasNextModelLoader()) {
      resourceClassIndex++;
      if (resourceClassIndex >= resourceClasses.size()) {
        sourceIdIndex++;
        if (sourceIdIndex >= sourceIds.size()) {
          return false;
        }
        resourceClassIndex = 0;
      }

      Key sourceId = sourceIds.get(sourceIdIndex);
      
      // ...
      
      // DiskLruCache的key
      currentKey =
          new ResourceCacheKey( // NOPMD AvoidInstantiatingObjectsInLoops
              helper.getArrayPool(),
              sourceId,
              helper.getSignature(),
              helper.getWidth(),
              helper.getHeight(),
              transformation,
              resourceClass,
              helper.getOptions());
              
      // 利用DecodeHelper获取DiskLruCacheWrapper,它是diskLruCache的包装类,之后根据key获取缓存文件
      cacheFile = helper.getDiskCache().get(currentKey);
      if (cacheFile != null) {
        sourceKey = sourceId;
        
        // 以缓存文件为输入model获取ModelLoader
        modelLoaders = helper.getModelLoaders(cacheFile);
        modelLoaderIndex = 0;
      }
    }

    loadData = null;
    boolean started = false;
    while (!started && hasNextModelLoader()) {
      ModelLoader<File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
      
      // 利用ModelLoader构建LoadData
      loadData =
          modelLoader.buildLoadData(
              cacheFile, helper.getWidth(), helper.getHeight(), helper.getOptions());
              
      // 如果loadData对应的dataClass有加载路径LoadPath,说明可以从数据源解码得到最终数据,则利用DataFetcher请求数据
      if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
        started = true;
        
        // 利用DataFetcher请求数据
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }

    return started;
}

private boolean hasNextModelLoader() {
    return modelLoaderIndex < modelLoaders.size();
}

@Override
public void onDataReady(Object data) {
    // 当数据加载完成后,会回调通知DecodeJob,onLoadFailed()类似。
    cb.onDataFetcherReady(
        sourceKey, data, loadData.fetcher, DataSource.RESOURCE_DISK_CACHE, currentKey);
}

DataCacheGenerator和SourceCacheGenerator也差不多,只是SourceCacheGenerator获取到数据之后会根据Engine#load(...)中设置的diskCacheStrategy来缓存数据。

// SourceCacheGenerator.java

// 待存储的数据(上次获取的数据)
private Object dataToCache;

private volatile ModelLoader.LoadData<?> loadData;


public boolean startNext() {

    // 如果有待存储的数据,则先存储数据
    if (dataToCache != null) {
      Object data = dataToCache;
      dataToCache = null;
      
      // 存储数据,存储完成后会创建DataCacheGenerator,之后就是通过DataCacheGenerator获取待加载数据
      cacheData(data); 
    }

    // 如果不为null则说明之前存储了数据,存储完成后通过DataCacheGenerator来获取待加载数据,获取成功则return,后面会在onDataFetcherReady(...)通知DecodeJob
    if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
      return true;
    }
    
    // 如果之前没有存储数据,或者有存储数据,但是DataCacheGenerator获取待加载数据失败,则通过DataFetcher获取数据
    sourceCacheGenerator = null;

    loadData = null;
    boolean started = false;
    while (!started && hasNextModelLoader()) {
      // 获取能够处理model的ModelLoader,从而buildLoadData,返回能够根据model获取数据的LoadDatas
      loadData = helper.getLoadData().get(loadDataListIndex++);
      
      // 1.如果根据磁盘缓存策略DiskCacheStrategy和LoadData的Fetcher对应的DataSource,表明获取的数据是可以缓存的,或者2.如果获取的数据有对应的加载路径LoadPath,则通过该LoadData的Fetcher获取数据
      if (loadData != null
          && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
              || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
        started = true;
        
        // 使用Fetcher获取数据
        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) {
            // 如果Generator请求数据用的LoadData就是当前请求所使用的LoadData,说明是同一个请求
            if (isCurrentRequest(toStart)) {
              onDataReadyInternal(toStart, data);
            }
          }

          @Override
          public void onLoadFailed(@NonNull Exception e) {
            if (isCurrentRequest(toStart)) {
              onLoadFailedInternal(toStart, e);
            }
          }
        });
}


void onDataReadyInternal(LoadData<?> loadData, Object data) {
    DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
    
    // 如果根据磁盘缓存策略DiskCacheStrategy和LoadData的Fetcher对应的DataSource,表明获取的数据是可以缓存的,则在Glide的线程池中重新执行DecodeJob,之后会重新执行该Generator,可以查看DecodeJob章节进行验证该逻辑
    if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
      
      // 暂存数据,reschedule()之后会重新执行SourceGenerator#startNext(),数据会在其中进行保存
      dataToCache = data;
      
      cb.reschedule();
    } else {
      cb.onDataFetcherReady(
          loadData.sourceKey,
          data,
          loadData.fetcher,
          loadData.fetcher.getDataSource(),
          originalKey);
    }
}

// 缓存数据
private void cacheData(Object dataToCache) {
    long startTime = LogTime.getLogTime();
    try {
    
      // 根据待缓存数据的Class,获取Registry在Glide中添加的Encoder
      Encoder<Object> encoder = helper.getSourceEncoder(dataToCache);
      
      // 这是一个包装类,包含待缓存数据、Encoder和Options,之后在DiskLruCacheWrapper中拿到缓存文件后,调用DataCacheWriter#write(file),其实就是调用Encoder#encode(data, file, options)通过输出流将数据写入缓存文件
      DataCacheWriter<Object> writer =
          new DataCacheWriter<>(encoder, dataToCache, helper.getOptions());
      originalKey = new DataCacheKey(loadData.sourceKey, helper.getSignature());
      
      // 利用DecodeHelper获取DiskLruCacheWrapper,它是DiskLruCache的包装类,然后将数据放入originalKey对应的缓存文件中
      helper.getDiskCache().put(originalKey, writer);
    } finally {
      // 释放DataFetcher中的资源
      loadData.fetcher.cleanup();
    }

    // 创建DataCacheGenerator,一会会通过DataCacheGenerator获取待加载的数据
    sourceCacheGenerator =
        new DataCacheGenerator(Collections.singletonList(loadData.sourceKey), helper, this);
}

DataCacheWriter是个包装类,实际还是通过Encoder在缓存数据的:

// DataCacheWriter.java

class DataCacheWriter<DataType> implements DiskCache.Writer {
  private final Encoder<DataType> encoder;
  private final DataType data;
  private final Options options;

  DataCacheWriter(Encoder<DataType> encoder, DataType data, Options options) {
    this.encoder = encoder;
    this.data = data;
    this.options = options;
  }

  // 在在DiskLruCacheWrapper中拿到缓存文件后,调用该方法
  @Override
  public boolean write(@NonNull File file) {
    return encoder.encode(data, file, options);
  }
}

随便看一个Encoder的实现吧:

public class StreamEncoder implements Encoder<InputStream> {
    
  public boolean encode(@NonNull InputStream data, @NonNull File file, @NonNull Options options) {
    byte[] buffer = byteArrayPool.get(ArrayPool.STANDARD_BUFFER_SIZE_BYTES, byte[].class);
    boolean success = false;
    OutputStream os = null;
    try {
      // 将输入流写入到缓存文件
      os = new FileOutputStream(file);
      int read;
      while ((read = data.read(buffer)) != -1) {
        os.write(buffer, 0, read);
      }
      os.close();
      success = true;
    } catch (IOException e) {
    } finally {
      // ... close stream
    }
    return success;
  }

}

LoadPath、DecodePath

由DecodeJob章节可以知道,通过Generator获取数据成功后,会通过LoadPath/DecodePath进行解码。

几个类的理解:

  1. LoadPath,可以这么理解:顾名思义,加载路径,从dataClass得到resourceClass,从而得到transcodeClass,内部包含dataClass、resourceClass、transcodeClass以及decodePath
  2. DecodePath,可以这么理解:顾名思义,解码路径,内部包含ResourceDecoder和ResourceTranscoder,以及DataClass、ResourceClass、TranscodeClass,利用ResourceDecoder可以将DataClass转化为ResourceClass,利用TranscodeClass可以将ResrouceClass转化为TranscodeClass
// LoadPath.java
public class LoadPath<Data, ResourceType, Transcode> {

  // 该LoadPath对应的dataClass
  private final Class<Data> dataClass;
  
  // 实际进行解码操作的是DecodePath
  private final List<? extends DecodePath<Data, ResourceType, Transcode>> decodePaths;
  
  
  public Resource<Transcode> load(
      DataRewinder<Data> rewinder,
      Options options,
      int width,
      int height,
      DecodePath.DecodeCallback<ResourceType> decodeCallback) {
    List<Throwable> throwables = Preconditions.checkNotNull(listPool.acquire());
    ...
    
    // 利用DecodePath中的Decoder、Transcoder进行解码
    return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);
    
    ...
  }
  
  
  // 利用DecodePath中的Decoder、Transcoder进行解码
  private Resource<Transcode> loadWithExceptionList(
      DataRewinder<Data> rewinder,
      Options options,
      int width,
      int height,
      DecodePath.DecodeCallback<ResourceType> decodeCallback,
      List<Throwable> exceptions) {
    Resource<Transcode> result = null;
    for (int i = 0, size = decodePaths.size(); i < size; i++) {
      DecodePath<Data, ResourceType, Transcode> path = decodePaths.get(i);
      
      // 使用DecodePath进行解码
      result = path.decode(rewinder, width, height, options, decodeCallback);
      if (result != null) {
        break;
      }
    }
    
    return result;
  }

}  

LoadPath相当于代理类,内部使用DecodePath来完成解码操作。

// DecodePath.java
public class DecodePath<DataType, ResourceType, Transcode> {
    
    // DecodePath对应的dataClass
    private final Class<DataType> dataClass;
    
    // 能够将dataClass转换为ResourceClass的ResourceDecoder
    private final List<? extends ResourceDecoder<DataType, ResourceType>> decoders;
    
    // 能够将ResourceClass转换为TranscodeClass的ResourceTranscoder
    private final ResourceTranscoder<ResourceType, Transcode> transcoder;
    
// 解码操作    
public Resource<Transcode> decode(
      DataRewinder<DataType> rewinder,
      int width,
      int height,
      Options options,
      DecodeCallback<ResourceType> callback)
      throws GlideException {
      
    // 使用ResourceDecoder将DataClass转换为ResourceClass
    Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
    
    // 回调到DecodeJob中,利用Trasformation对ResourceClass进行变换操作
    Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
    
    // 使用ResourceTranscoder将变换后的资源转换为最终结果
    return transcoder.transcode(transformed, options);
  }
  

private Resource<ResourceType> decodeResource(
      DataRewinder<DataType> rewinder, int width, int height, @NonNull Options options)
      throws GlideException {
    ...
    return decodeResourceWithList(rewinder, width, height, options, exceptions);
    ...
  }
  
  
private Resource<ResourceType> decodeResourceWithList(
      DataRewinder<DataType> rewinder,
      int width,
      int height,
      @NonNull Options options,
      List<Throwable> exceptions) {
      
    Resource<ResourceType> result = null;
    
    for (int i = 0, size = decoders.size(); i < size; i++) {
      ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);
      
      // 使用DataRewinder将数据类型为Stream类型的数据重置到起始位置,并返回数据
      DataType data = rewinder.rewindAndGet();
      
      // 如果该decoder能够处理data,则使用decoder进行解码
      if (decoder.handles(data, options)) {
        data = rewinder.rewindAndGet();
        result = decoder.decode(data, width, height, options);
      }

      if (result != null) {
        break;
      }
    }
    return result;
  }
}

DeferredEncodeManager<Z>

由DecodeJob章节可以知道,数据解码成功后,会通过DeferredEncodeManager进行缓存,它是DecodeJob的内部类。

它其实是个辅助类,实际的缓存工作是由ResourceEncoder完成的。

private static class DeferredEncodeManager<Z> {
    private Key key;
    
    // 缓存数据的ResourceEncoder
    private ResourceEncoder<Z> encoder;
    
    // 待缓存的数据
    private LockedResource<Z> toEncode;
    
    // ResourceDecoder解码原始数据后,在DecodeJob#onResourceDecoded(DataSource dataSource, Resource<Z> decoded)方法中调用,保存待缓存数据(处理(变换)后的数据DecodedClass/TransformedClass,不是最终数据TranscodedClass)和对应的key以及ResourceEncoder
    <X> void init(Key key, ResourceEncoder<X> encoder, LockedResource<X> toEncode) {
      this.key = key;
      this.encoder = (ResourceEncoder<Z>) encoder;
      this.toEncode = (LockedResource<Z>) toEncode;
    }
    
    
    // ResourceTranscoder解码DecodedClass/TransformedClass后,在DecodeJob#notifyEncodeAndRelease(...)中调用,进行缓存DecodedClass/TransformedClass
    void encode(DiskCacheProvider diskCacheProvider, Options options) {
      GlideTrace.beginSection("DecodeJob.encode");
      try {
        // 获取DiskLruCacheWrapper,并构建DataCacheWriter用于缓存文件,具体参考DataFetcherGenerator章节Encoder缓存数据相关内容
        diskCacheProvider
            .getDiskCache()
            .put(key, new DataCacheWriter<>(encoder, toEncode, options));
      } finally {
        toEncode.unlock();
        GlideTrace.endSection();
      }
    }
    
    boolean hasResourceToEncode() {
      return toEncode != null;
    }
}

DecodeHelper

DecodeHelper是一个辅助类,每个DecodeJob对应一个DecodeHelper,在DecodeJob#init(...)中进行初始化,为DecodeJob提供能够处理Model的ModelLoader、LoadData和对应的Key、DiskCache、DiskCacheStrategy、LoadPath、Transformation、以及缓存数据用的Encoder等。

final class DecodeHelper<Transcode> {
  private final List<LoadData<?>> loadData = new ArrayList<>();
  private final List<Key> cacheKeys = new ArrayList<>();

  private GlideContext glideContext;
  private Object model;
  private int width;
  private int height;
  private Class<?> resourceClass;
  private DecodeJob.DiskCacheProvider diskCacheProvider;    // Engine中初始化了LazyDiskCacheProvider,传给DecodeJobFactory->DecodeJob->DecodeHelper
  private Options options;
  private Map<Class<?>, Transformation<?>> transformations;
  private Class<Transcode> transcodeClass;
  private DiskCacheStrategy diskCacheStrategy;
  
  
  // 在DecodeJob#init(...)中调用进行初始化
  <R> void init(
      GlideContext glideContext,
      Object model,
      Key signature,
      int width,
      int height,
      DiskCacheStrategy diskCacheStrategy,
      Class<?> resourceClass,
      Class<R> transcodeClass,
      Priority priority,
      Options options,
      Map<Class<?>, Transformation<?>> transformations,
      boolean isTransformationRequired,
      boolean isScaleOnlyOrNoTransform,
      DiskCacheProvider diskCacheProvider) {
    this.glideContext = glideContext;
    this.model = model;
    this.signature = signature;
    this.width = width;
    this.height = height;
    this.diskCacheStrategy = diskCacheStrategy;
    this.resourceClass = resourceClass;
    
    this.diskCacheProvider = diskCacheProvider; // 实例是LazyDiskCacheProvider,在Engine中设置给DecodeJobFactory,之后的传递路径是DecodeJobFactory -> DecodeJob -> DecodeHelper。
    
    this.transcodeClass = (Class<Transcode>) transcodeClass;
    this.priority = priority;
    this.options = options;
    this.transformations = transformations;
    this.isTransformationRequired = isTransformationRequired;
    this.isScaleOnlyOrNoTransform = isScaleOnlyOrNoTransform;
  }
  
  // 获取DiskCache,它有两个子类,一个是DiskCacheAdapter(空实现),一个是DiskLruCacheWrapper(DiskLruCache的包装类)
  DiskCache getDiskCache() {
    return diskCacheProvider.getDiskCache();
  }

  // 获取磁盘缓存策略,用于判断请求结果(包括原始数据和处理后的数据)是否可以缓存,详见DiskCacheStrategy章节
  DiskCacheStrategy getDiskCacheStrategy() {
    return diskCacheStrategy;
  }
  
  // 获取返回结果的Class,例如BitmapDrawable
  Class<?> getTranscodeClass() {
    return transcodeClass;
  }

  // 获取请求参数的Class,例如RequestManager#load(String url),ModelClass就是Strin.class
  Class<?> getModelClass() {
    return model.getClass();
  }
    
  // 中间类型,从数据源返回的类型Data编码成的类型,例如Bitmap、Drawable、GifDrawable、BitmapDrawable、File等。举个例子:例如由InputStream编码成Bitmap。可以参考Engine的构造函数中,Registry#append(...)添加的类型。
  List<Class<?>> getRegisteredResourceClasses() {
    return glideContext
        .getRegistry()
        .getRegisteredResourceClasses(model.getClass(), resourceClass, transcodeClass);
  }

  // 是否有符合从DataClass->ResourceClass->TranscodeClass的LoadPath
  boolean hasLoadPath(Class<?> dataClass) {
    return getLoadPath(dataClass) != null;
  }

  // 获取从DataClass->ResourceClass->TranscodeClass的LoadPath
  <Data> LoadPath<Data, ?, Transcode> getLoadPath(Class<Data> dataClass) {
    return glideContext.getRegistry().getLoadPath(dataClass, resourceClass, transcodeClass);
  }
  
  // 获取能够以缓存文件file为输入得到数据的ModelLoader
  List<ModelLoader<File, ?>> getModelLoaders(File file)
      throws Registry.NoModelLoaderAvailableException {
    return glideContext.getRegistry().getModelLoaders(file);
  }
  
  // 获取能够以Model为输入得到数据的LoadData
  List<LoadData<?>> getLoadData() {
    if (!isLoadDataSet) {
      isLoadDataSet = true;
      loadData.clear();
      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;
  }
  
  // 获取能够以Model为输入得到数据的LoadData对应的Key
  List<Key> getCacheKeys() {
    if (!isCacheKeysSet) {
      isCacheKeysSet = true;
      cacheKeys.clear();
      List<LoadData<?>> loadData = getLoadData();
      //noinspection ForLoopReplaceableByForEach to improve perf
      for (int i = 0, size = loadData.size(); i < size; i++) {
        LoadData<?> data = loadData.get(i);
        if (!cacheKeys.contains(data.sourceKey)) {
          cacheKeys.add(data.sourceKey);
        }
        for (int j = 0; j < data.alternateKeys.size(); j++) {
          if (!cacheKeys.contains(data.alternateKeys.get(j))) {
            cacheKeys.add(data.alternateKeys.get(j));
          }
        }
      }
    }
    return cacheKeys;
  }

  // 获取能够缓存data的Encoder
  <X> Encoder<X> getSourceEncoder(X data) throws Registry.NoSourceEncoderAvailableException {
    return glideContext.getRegistry().getSourceEncoder(data);
  }
  
}

ModelLoader、LoadData、DataFetcher

这三个类主要是用于根据model请求数据的。

三者的UML图如下:


Registry、ModelLoader、LoadData、DataFetcher关系图.png

在Glide章节中,我们知道Registry注册了很多Entry,其中包括注册了ModelLoaderFactory,而这个ModelLoaderFactory最终会被包装成Entry,保存在MultiModelLoaderFactory中:

// Glide.java
registry.append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())
// Registry.java
public <Model, Data> Registry append(
      @NonNull Class<Model> modelClass,
      @NonNull Class<Data> dataClass,
      @NonNull ModelLoaderFactory<Model, Data> factory) {
    modelLoaderRegistry.append(modelClass, dataClass, factory);
    return this;
}
// ModelLoaderRegistry.java
public synchronized <Model, Data> void append(
      @NonNull Class<Model> modelClass,
      @NonNull Class<Data> dataClass,
      @NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
    multiModelLoaderFactory.append(modelClass, dataClass, factory); // 1
    cache.clear();
}
// MultiModelLoaderFactory.java

private final List<Entry<?, ?>> entries = new ArrayList<>();

synchronized <Model, Data> void append(
      @NonNull Class<Model> modelClass,
      @NonNull Class<Data> dataClass,
      @NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
    add(modelClass, dataClass, factory, /*append=*/ true);  // 2
}

private <Model, Data> void add(
      @NonNull Class<Model> modelClass,
      @NonNull Class<Data> dataClass,
      @NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory,
      boolean append) {
    Entry<Model, Data> entry = new Entry<>(modelClass, dataClass, factory);
    entries.add(append ? entries.size() : 0, entry); // 3
}

之后在DecodedJob中,我们知道,请求数据是由DataFetcherGenerator完成的,具体可以参考DecodeJob和DataFetcherGenerator章节。

而DataFetcherGenerator则是通过DecodeHelper获取Registry中注册的能够处理model的Entry的ModelLoaderFactory,从而build出ModelLoader,进而得到LoadData。

例如SourceGenerator,这里只展示部分代码,具体灿开DataFetcherGenerator章节。

// SourceGenerator.java

public boolean startNext() {
    ...
    
    // 1. 通过DecodeHelper获取LoadData
    loadData = helper.getLoadData().get(loadDataListIndex++); 
    ...
}
// DecodeHelper.java

List<LoadData<?>> getLoadData() {
    ...
    
    // 2. 获取Registry中注册的能够处理model的Entry,并用其中的ModelLoaderFactory创建ModelLoader
    List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model); 
    
    ...
    
    // 3. 通过ModelLoader创建LoadData
    ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
    LoadData<?> current = modelLoader.buildLoadData(model, width, height, options); 
    
    ...
}

得到LoadData之后,就会用其中的DataFetcher请求数据,具体可以参考DataFetcherGenerator章节。

这里简单看下HttpGlideUrlLoader,以及对应的Factory和Fetcher吧:

// HttpGlideUrlLoader.java
public class HttpGlideUrlLoader implements ModelLoader<GlideUrl, InputStream> {

    // 返回LoadData,内部包含实际进行请求的Fetcher
    @Override
    public LoadData<InputStream> buildLoadData(GlideUrl model, int width, int height, Options options) {
        return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
    }
    
    // 用于判断当前ModelLoader是否可以处理model。
    // 例如UrlUriModelLoader判断是否可以处理model的条件是uri的schema是否是http或https
    @Override
    public boolean handles(GlideUrl model) {
         return true;
    }
    
    // 创建该ModelLoader的ModelLoaderFactory
    public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
        
        // 创建ModelLoader
        public ModelLoader<GlideUrl, InputStream> build(MultiModelLoaderFactory multiFactory) {
              return new HttpGlideUrlLoader(modelCache);
        }
        
    }
}

真正实现请求的是DataFetcher:

// HttpUrlFetcher.java

// HttpUrlFetcher的model是GlideUrl,data是InputStream
public class HttpUrlFetcher implements DataFetcher<InputStream> {

  private final GlideUrl glideUrl;
  
  // 工厂类,用于创建HttpURLConnection
  private final HttpUrlConnectionFactory connectionFactory;
  
  private HttpURLConnection urlConnection;
  
  // 请求得到的数据
  private InputStream stream;
  
public void loadData(Priority priority, DataCallback<? super InputStream> callback) {
    
    try {
      // 执行请求,得到数据数据流
      InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
      
      // 回调通知DataFetcherGenerator或MultiModelLoader
      callback.onDataReady(result);
    } catch (IOException e) {
    
      callback.onLoadFailed(e);
    }
  }
  
  // 执行请求,得到数据数据流
  private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl, Map<String, String> headers) {

    // ... 省略一些抛异常的代码
    
    // 通过工厂类创建HttpURLConnection,例如url.openConnection()
    urlConnection = connectionFactory.build(url);
    
    // ... 省略一些给urlConnection设置header、timeout等参数的代码

    // 请求服务器
    urlConnection.connect();
    
    // 获取输入流,以便在cleanup()中关闭,避免(ResponseBody)资源泄漏?
    stream = urlConnection.getInputStream();
    
    if (isCancelled) {
      return null;
    }
    
    // 响应码
    final int statusCode = urlConnection.getResponseCode();
    
    if (isHttpOk(statusCode)) {
    
      // 请求成功,则从连接获取输入流
      return getStreamForSuccessfulRequest(urlConnection);
    } else if (isHttpRedirect(statusCode)) {
      
      // ... 省略重定向相关代码
    } else if (statusCode == INVALID_STATUS_CODE) {
      // 无法识别的错误码,请求失败
      throw new HttpException(statusCode);
    } else {
      // 请求失败
      throw new HttpException(urlConnection.getResponseMessage(), statusCode);
    }
  }
 
 
  private static boolean isHttpOk(int statusCode) {
    return statusCode / 100 == 2;
  }
  
  private static boolean isHttpRedirect(int statusCode) {
    return statusCode / 100 == 3;
  }
  
  // 从连接获取输入流
  private InputStream getStreamForSuccessfulRequest(HttpURLConnection urlConnection) {
    if (TextUtils.isEmpty(urlConnection.getContentEncoding())) {
      // ContentEncoding为空,说明返回的是未压缩的响应正文,则Response中的响应头包含ContentLength!=-1
      int contentLength = urlConnection.getContentLength();
      stream = ContentLengthInputStream.obtain(urlConnection.getInputStream(), contentLength);
    } else {
      // ContentEncoding不为空,说明返回的是压缩过的响应正文,ContentLength==-1,则直接获取数据流,之后需要用ContentEncoding的编码格式进行解码,例如gzip
      stream = urlConnection.getInputStream();
    }
    return stream;
  }
  
  // 执行资源清理工作
  @Override
  public void cleanup() {
    if (stream != null) {
        stream.close();
    }
    if (urlConnection != null) {
      urlConnection.disconnect();
    }
    urlConnection = null;
  }
  
  
  // 取消请求数据操作
  @Override
  public void cancel() {
    isCancelled = true;
  }

}

得到DataFetcher后,会包装成LoadData,它是一个包装类,其实啥也没干,位于ModelLoader的内部类:

// ModelLoader.java
public interface ModelLoader<Model, Data> {
  
  class LoadData<Data> {
    public final Key sourceKey;
    public final List<Key> alternateKeys;
    public final DataFetcher<Data> fetcher;

    public LoadData(
        @NonNull Key sourceKey,
        @NonNull List<Key> alternateKeys,
        @NonNull DataFetcher<Data> fetcher) {
      this.sourceKey = Preconditions.checkNotNull(sourceKey);
      this.alternateKeys = Preconditions.checkNotNull(alternateKeys);
      this.fetcher = Preconditions.checkNotNull(fetcher);
    }
  }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,561评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,218评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,162评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,470评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,550评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,806评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,951评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,712评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,166评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,510评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,643评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,306评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,930评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,745评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,983评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,351评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,509评论 2 348

推荐阅读更多精彩内容