美文网首页
Glide源码解析四——Engine相关(从数据源获取数据)

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

作者: GIndoc | 来源:发表于2022-06-17 11:38 被阅读0次

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

    相关文章

      网友评论

          本文标题:Glide源码解析四——Engine相关(从数据源获取数据)

          本文链接:https://www.haomeiwen.com/subject/ideqvrtx.html