Glide原理之Engine#load

Engine类是Glide框架加载图片的入口。接下来我们分析load的过程。

1. Engine#load

public <R> LoadStatus load(
      GlideContext glideContext,
      Object model,
      Key signature,
      int width,
      int height,
      Class<?> resourceClass,
      Class<R> transcodeClass,
      Priority priority,
      DiskCacheStrategy diskCacheStrategy,
      Map<Class<?>, Transformation<?>> transformations,
      boolean isTransformationRequired,
      boolean isScaleOnlyOrNoTransform,
      Options options,
      boolean isMemoryCacheable,
      boolean useUnlimitedSourceExecutorPool,
      boolean useAnimationPool,
      boolean onlyRetrieveFromCache,
      ResourceCallback cb,
      Executor callbackExecutor) {
    long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
    //生成用于缓存文件的key
    EngineKey key =
        keyFactory.buildKey(
            model,
            signature,
            width,
            height,
            transformations,
            resourceClass,
            transcodeClass,
            options);

    EngineResource<?> memoryResource;
    synchronized (this) {
      //从缓存中读取
      memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
      //未命中缓存,去下载
      if (memoryResource == null) {
        return waitForExistingOrStartNewJob(
            glideContext,
            model,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            options,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache,
            cb,
            callbackExecutor,
            key,
            startTime);
      }
    }

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

生成缓存文件的Key,根据生成的Key通过loadFromMemory方法获取内存缓存文件。

2. Engine#loadFromMemory

  @Nullable
  private EngineResource<?> loadFromMemory(
      EngineKey key, boolean isMemoryCacheable, long startTime) {
    //内存缓存不可用,直接返回
    if (!isMemoryCacheable) {
      return null;
    }
    //获取Active缓存,命中直接返回
    EngineResource<?> active = loadFromActiveResources(key);
    if (active != null) {
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from active resources", startTime, key);
      }
      return active;
    }
    //获取内存缓存,命中直接返回
    EngineResource<?> cached = loadFromCache(key);
    if (cached != null) {
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from cache", startTime, key);
      }
      return cached;
    }

    return null;
  }

  @Nullable
  private EngineResource<?> loadFromActiveResources(Key key) {
    EngineResource<?> active = activeResources.get(key);
    if (active != null) {
      //资源使用计数器+1
      active.acquire();
    }
    return active;
  }

  private EngineResource<?> loadFromCache(Key key) {
    EngineResource<?> cached = getEngineResourceFromCache(key);
    if (cached != null) {
      //资源使用计数器+1
      cached.acquire();
      //将内存缓存放到Active缓存中
      activeResources.activate(key, cached);
    }
    return cached;
  }

若未命中内存缓存文件,则调用waitForExistingOrStartNewJob方法获取磁盘缓存文件,若没有命中磁盘缓存文件,会发送网络请求服务端资源。

3. Engine#waitForExistingOrStartNewJob

private <R> LoadStatus waitForExistingOrStartNewJob(
      GlideContext glideContext,
      Object model,
      Key signature,
      int width,
      int height,
      Class<?> resourceClass,
      Class<R> transcodeClass,
      Priority priority,
      DiskCacheStrategy diskCacheStrategy,
      Map<Class<?>, Transformation<?>> transformations,
      boolean isTransformationRequired,
      boolean isScaleOnlyOrNoTransform,
      Options options,
      boolean isMemoryCacheable,
      boolean useUnlimitedSourceExecutorPool,
      boolean useAnimationPool,
      boolean onlyRetrieveFromCache,
      ResourceCallback cb,
      Executor callbackExecutor,
      EngineKey key,
      long startTime) {
    //Job 一个负责缓存EngineJob的管理类,里面存放了Key与EngineJob的Map对象。
    //jobs中有两个队列,一个是正常的jobs集合,一个是只访问缓存的onlyCacheJobs集合,
    //如果onlyRetrieveFromCache是true,从onlyCacheJobs获取,反之从jobs获取。
    //根据key获取到已有的EngineJob,则直接返回
    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
      current.addCallback(cb, callbackExecutor);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Added to existing load", startTime, key);
      }
      return new LoadStatus(cb, current);
    }

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

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

    jobs.put(key, engineJob);

    engineJob.addCallback(cb, callbackExecutor);
    engineJob.start(decodeJob);

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

4. EngineJob#start

  public synchronized void start(DecodeJob<R> decodeJob) {
    this.decodeJob = decodeJob;
    //根据是否从缓存中加载、是否使用无限制大小线程池、是否使用动画线程池等条件得到相应的线程池。
    GlideExecutor executor =
        decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
    //执行DecodeJob#run方法
    executor.execute(decodeJob);
  }

  private GlideExecutor getActiveSourceExecutor() {
    return useUnlimitedSourceGeneratorPool
        ? sourceUnlimitedExecutor
        : (useAnimationPool ? animationExecutor : sourceExecutor);
  }

5.DecodeJob#run

// We need to rethrow only CallbackException, but not other types of Throwables.
  @SuppressWarnings("PMD.AvoidRethrowingException")
  @Override
  public void run() {
    try {
      if (isCancelled) {
        notifyFailed();
        return;
      }
      //执行请求
      runWrapped();
    } catch (CallbackException e) {
     
      throw e;
    } catch (Throwable t) {
     
      if (stage != Stage.ENCODE) {
        throwables.add(t);
        notifyFailed();
      }
      if (!isCancelled) {
        throw t;
      }
      throw t;
    } finally {
      if (localFetcher != null) {
        localFetcher.cleanup();
      }
      GlideTrace.endSection();
    }
  }

6.DecodeJob#runWrapped

  private void runWrapped() {
    //执行原因,第一次执行,值为INITIALIZE
    switch (runReason) {
      case INITIALIZE:
        stage = getNextStage(Stage.INITIALIZE);
        currentGenerator = getNextGenerator();
        runGenerators();
        break;
      case SWITCH_TO_SOURCE_SERVICE:
        runGenerators();
        break;
      case DECODE_DATA:
        decodeFromRetrievedData();
        break;
      default:
        throw new IllegalStateException("Unrecognized run reason: " + runReason);
    }
  }
  //首先明确几种装状态有利于阅读
  //RESOURCE_CACHE:原始数据经过转换处理过的数据;
  //DATA_CACHE:从服务端获取的原始数据;
  //SOURCE:发送网络请求获取数据
  private Stage getNextStage(Stage current) {
    switch (current) {
      case INITIALIZE:
        //根据磁盘缓存策略,判断使用原始数据缓存,还是使用转换处理过的缓存数据。
        return diskCacheStrategy.decodeCachedResource()
            ? Stage.RESOURCE_CACHE
            : getNextStage(Stage.RESOURCE_CACHE);
      case RESOURCE_CACHE:
        //根据缓存策略,判断是否使用原始文件缓存。
        return diskCacheStrategy.decodeCachedData()
            ? Stage.DATA_CACHE
            : getNextStage(Stage.DATA_CACHE);
      case DATA_CACHE:
        // Skip loading from source if the user opted to only retrieve the resource from cache.
        //如果是只是用缓存,那么就返回FINISH,否则返回SOURCE
        return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
      case SOURCE:
      case FINISHED:
        return Stage.FINISHED;
      default:
        throw new IllegalArgumentException("Unrecognized stage: " + current);
    }
  }

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

 首先明确几种状态有利于阅读
       RESOURCE_CACHE:原始数据经过转换处理过的数据;
       DATA_CACHE:缓存在本地的原始数据;
       SOURCE:发送网络请求获取数据

runWrapped方法的逻辑就是依次执行这三种状态。

7. DecodeJob#runGenerator

 private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    while (!isCancelled
        && currentGenerator != null
        && !(isStarted = currentGenerator.startNext())) {
      stage = getNextStage(stage);
      currentGenerator = getNextGenerator();

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

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

通过while循环获取到能够返回相应文件的DataFetcherGenerator,并调用statNext方法获取数据。

猜你喜欢

转载自blog.csdn.net/gjd1988/article/details/100121627