Glide源码分析(五),EngineJob与DecodeJob代码详细加载过程

Glide源码分析(三),Engine加载资源过程文中,我们分析到Engine#load的最后一步,创建好了一对EngineJob和DecodeJob,随之调用EngineJob的start方法,启动加载任务。下面分析整个一个执行过程,文中相关情景下的方法特定调用的结果是还是基于一下这段code,虽然是由特殊入口,并不影响我们理解整个框架,反而是一个很好的突破口,理解代码的思想。示例代码如下:

       Glide.with(this)
                .load("https://p.upyun.com/docs/cloud/demo.jpg")
                .into(imageView);

此时的情景就是加载一个普通的http url对象。下面我们开始分析,加载的起点,也就是从EngineJob#start开始。

1. EngineJob#start

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

这个方法是根据当前条件,选取一个GlideExecutor,它实现了ExecutorService,然后由它去执行decodeJob。通过decodeJob的willDecodeFromCache方法,决定是使用哪一个。Glide里面,封装了很几种类型的线程池对象,这里无需深究哪个线程池这个细节。显然DecodeJob是一个Runnable对象,最终执行之后,都是触发DecodeJob的run方法。

2.DecodeJob#run

 @Override
  public void run() {
    // This should be much more fine grained, but since Java's thread pool implementation silently
    // swallows all otherwise fatal exceptions, this will at least make it obvious to developers
    // that something is failing.
    GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)", model);
    // Methods in the try statement can invalidate currentFetcher, so set a local variable here to
    // ensure that the fetcher is cleaned up either way.
    DataFetcher<?> localFetcher = currentFetcher;
    try {
      if (isCancelled) {
        notifyFailed();
        return;
      }
      runWrapped();
    } catch (Throwable t) {
      // Catch Throwable and not Exception to handle OOMs. Throwables are swallowed by our
      // usage of .submit() in GlideExecutor so we're not silently hiding crashes by doing this. We
      // are however ensuring that our callbacks are always notified when a load fails. Without this
      // notification, uncaught throwables never notify the corresponding callbacks, which can cause
      // loads to silently hang forever, a case that's especially bad for users using Futures on
      // background threads.
      if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "DecodeJob threw unexpectedly"
            + ", isCancelled: " + isCancelled
            + ", stage: " + stage, t);
      }
      // When we're encoding we've already notified our callback and it isn't safe to do so again.
      if (stage != Stage.ENCODE) {
        throwables.add(t);
        notifyFailed();
      }
      if (!isCancelled) {
        throw t;
      }
    } finally {
      // Keeping track of the fetcher here and calling cleanup is excessively paranoid, we call
      // close in all cases anyway.
      if (localFetcher != null) {
        localFetcher.cleanup();
      }
      GlideTrace.endSection();
    }
  }

执行run方法时候,首先检查isCancelled标志位,它是一个volatile变量,保证了多线程之间的可见性,由此可知道DecodeJob是支持取消的。如果此时,已经被取消,则会调用notifyFailed方法,它里面主要是通过callback回调告知上层调用者,这里就是EngineJob,其二是清理和重置DecodeJob里面的一些资源。另外如果未被取消,如果有任何异常出现,则会进入catch方法块,也会看条件进行一些回调和清理资源,同时在finally代码块中,执行已经结束,localFetcher记录着当前的currentFetcher对象,这个时候会通知DataFetcher的cleanup清理资源,因为DecodeJob是可被复用的,显然第一次运行localFetcher是null,后面我们分析到了这个再具体看看它的用处。下面我们分析重点方法,runWapped这个的执行逻辑。

3. DecodeJon#runWapped

  private void runWrapped() {
    switch (runReason) {
      case INITIALIZE:
        stage = getNextStage(Stage.INITIALIZE);
        currentGenerator = getNextGenerator();
        runGenerators();
        break;
      case SWITCH_TO_SOURCE_SERVICE:
        runGenerators();
        break;
      case DECODE_DATA:
        decodeFromRetrievedData();
        break;
      default:
        throw new IllegalStateException("Unrecognized run reason: " + runReason);
    }
  }

   private Stage getNextStage(Stage current) {
    switch (current) {
      case INITIALIZE:
        return diskCacheStrategy.decodeCachedResource()
            ? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
      case RESOURCE_CACHE:
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值