Glide源码解析(三)Engine

SingleRequest

上一篇分析到生成Request,接下来我们直接从SingleRequest子类开始阅读。

大致的流程:begin -> onSizeReady->engine.load

public void begin() {
    synchronized (requestLock) {
      ...
      //model为空回调失败
      if (model == null) {
        if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
          width = overrideWidth;
          height = overrideHeight;
        }
        int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
        onLoadFailed(new GlideException("Received null model"), logLevel);
        return;
      }

      //Status.RUNNING抛异常
      if (status == Status.RUNNING) {
        throw new IllegalArgumentException("Cannot restart a running request");
      }
      //Status.COMPLETE,回调onResourceReady
      if (status == Status.COMPLETE) {
        onResourceReady(resource, DataSource.MEMORY_CACHE, false);
        return;
      }

      experimentalNotifyRequestStarted(model);

      cookie = GlideTrace.beginSectionAsync(TAG);
      status = Status.WAITING_FOR_SIZE;
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
       //输出大小确认
        onSizeReady(overrideWidth, overrideHeight);
      } else {
       //输出大小不确认,开始获取大小
        target.getSize(this);
      }


      if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
          && canNotifyStatusChanged()) {
       //ImageView设置占位图
        target.onLoadStarted(getPlaceholderDrawable());
      }
    }
  }

begin方法处理了两种逻辑:

  1. 判断Request各种状态,然后回调
  2. 判断输出大小是否确认。确认的情况调用onSizeReady。不确认的情况调用getSize,getSize方法传递的参数是callback,所以等待大小确认后,最后还是回调到onSizeReady

getSize

如果into的是ImageView,生成的是ImageViewTarget。

void getSize(@NonNull SizeReadyCallback cb) {
     ....
      if (layoutListener == null) {
        ViewTreeObserver observer = view.getViewTreeObserver();
        layoutListener = new SizeDeterminerLayoutListener(this);
        observer.addOnPreDrawListener(layoutListener);
      }
    }

监听的原理是通过ViewTreeObserver,view大小确认后,最后执行到关键方法getTargetDimen

private int getTargetDimen(int viewSize, int paramSize, int paddingSize) {
      //布局xml固定大小的情况
      int adjustedParamSize = paramSize - paddingSize;
      if (adjustedParamSize > 0) {
        return adjustedParamSize;
      }

      //martch_parent的情况,需要等待view的大小测量成功
      int adjustedViewSize = viewSize - paddingSize;
      if (adjustedViewSize > 0) {
        return adjustedViewSize;
      }

      //WRAP_CONTENT取屏幕大小
      if (!view.isLayoutRequested() && paramSize == LayoutParams.WRAP_CONTENT) {
        return getMaxDisplayLength(view.getContext());
      }
      return PENDING_SIZE;
    }

大小确认后回调到SingleRequest.OnSizeReady方法,里面主要是执行到engine.load方法

Engine

public <R> LoadStatus load(...) {
    //生成key
    EngineKey key =
        keyFactory.buildKey(...);
   
    //根据key取缓存
    EngineResource<?> memoryResource;
    synchronized (this) {
      memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);

    //没缓存,开始异步任务获取图片资源
      if (memoryResource == null) {
        return waitForExistingOrStartNewJob(...);
      }
}

Key

public interface Key {

  void updateDiskCacheKey(@NonNull MessageDigest messageDigest);


  @Override
  boolean equals(Object o);


  @Override
  int hashCode();
}
  • updateDiskCacheKey是用于生成磁盘缓存的key。原理是通过MessageDigest.update(...)方法更新数据摘要,MessageDigest.digest()输出摘要,然后根据摘要key获取已经缓存好的磁盘文件
  • equals和hashCode都是object的方法,目的是确保实现Key接口的子类重写equals和hahCode,判断Key的相同性

上面engine生成的EngineKey代码如下:

EngineKey key =
        keyFactory.buildKey(
            model,
            signature,
            width,
            height,
            transformations,
            resourceClass,
            transcodeClass,
            options);

buildKey的入参8个,需要8个值相同,EngineKey才会相同。第二个入参signature是通过RequestBuilder.signature(@NonNull Key signature)设置的,作用是预留扩展性,例如我们想把app的版本号加进key判断,就可以自定义key更改配置。

loadFromMemory

 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;
  }
  • 内存缓存有两种。loadFromActiveResources(key)指活跃中ImageView显示中的资源。loadFromCache(key)是不活跃的资源已经不在ImageView显示,存储在MemoryCache。
  • isMemoryCacheable字段是通过RequestBuilder.skipMemoryCache(boolean skip)设置,默认值支持缓存

waitForExistingOrStartNewJob

里面的逻辑比较简单,通过工厂生成EngineJob和DecodeJob,然后调用start开始加载。EngineJob和DecodeJob这两个类我们后面再详细分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值