美文网首页
Glide4.0x源码浅析(二)

Glide4.0x源码浅析(二)

作者: 小川君 | 来源:发表于2018-09-28 16:28 被阅读0次

上篇说到了RequestManager,也就是Glide.with()最后的返回类型
根据调用链的流程,下面就是传入图片源了,这个图片源可以是一个地址也可以是file、Uri、字节等。总的来说就是既可以联网加载网络图片也就是加载本地的图片文件或者数据
我们以String地址为例
RequestManager#load():

RequestManager#load():
 public RequestBuilder<Drawable> load(@Nullable Integer resourceId) {
    return asDrawable().load(resourceId);
  }

RequestManager#asDrawable():
  public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
  }  
  
RequestManager#as()
  public <ResourceType> RequestBuilder<ResourceType> as(
      @NonNull Class<ResourceType> resourceClass) {
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }  

从上面的代码可以看出,调用RequestManager中的load方法最终调用的是RequestBuilder中的load方法,asDrawable是创建一个图片类型为Drawable类型的RequestBuilder请求
所以对于调用链我们还可以分开来调用Glide.with(mContext).as(Drawable.class).load("").into()可以选择我们的图片类型,不过大部分都是Drawable,而Glide也只对Btimap和Drawable做封装,下面会说到。

RequestBuilder#load()
  public RequestBuilder<TranscodeType> load(@Nullable String string) {
    return loadGeneric(string);
  }
  
RequestBuilder#loadGeneric()  
  private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
    this.model = model;
    isModelSet = true;
    return this;
  }  

RequsetBuilder中的load方法主要是将图片源保存起来,并设置是否设置了图片源的标识isModelSet = true最后返回了RequestBuilder本身
然后就是将目标view传入进去

  @NonNull
  public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    Util.assertMainThread();
    Preconditions.checkNotNull(view);

    RequestOptions requestOptions = this.requestOptions;
    if (!requestOptions.isTransformationSet()
        && requestOptions.isTransformationAllowed()
        && view.getScaleType() != null) {
      // Clone in this method so that if we use this RequestBuilder to load into a View and then
      // into a different target, we don't retain the transformation applied based on the previous
      // View's scale type.
      switch (view.getScaleType()) {
        case CENTER_CROP:
          requestOptions = requestOptions.clone().optionalCenterCrop();
          break;
        case CENTER_INSIDE:
          requestOptions = requestOptions.clone().optionalCenterInside();
          break;
        case FIT_CENTER:
        case FIT_START:
        case FIT_END:
          requestOptions = requestOptions.clone().optionalFitCenter();
          break;
        case FIT_XY:
          requestOptions = requestOptions.clone().optionalCenterInside();
          break;
        case CENTER:
        case MATRIX:
        default:
          // Do nothing.
      }
    }

    return into(
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions);
  }

前一部分是是一些配置信息,这个放到后面再说,我们直接看into()

RequestBuilder#into
inti()有三个参数,先看第一个

GlideContext#buildImageViewTarget():
  @NonNull
  public <X> ViewTarget<ImageView, X> buildImageViewTarget(
      @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
    return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
  }
  
ImageViewTargetFactory#buildTarget():  
  public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
      @NonNull Class<Z> clazz) {
    if (Bitmap.class.equals(clazz)) {
      return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
    } else if (Drawable.class.isAssignableFrom(clazz)) {
      return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
    } else {
      throw new IllegalArgumentException(
          "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
    }
  }  

这里会通过ImageViewFactory创建一个ImageViewTarget对象,并将我们的目标view传入其中,我们可以看到默认的有两种ImageViewTarget类型是Drawable和Bitmap类型的,如果是其他的怎么报出异常

into的第二个参数我们从注释里面看是一个监听,第三个则是图片的配置信息

  private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      @NonNull RequestOptions options) {
    Util.assertMainThread();
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

    options = options.autoClone();
    Request request = buildRequest(target, targetListener, options);

    Request previous = target.getRequest();
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
      request.recycle();
      // If the request is completed, beginning again will ensure the result is re-delivered,
      // triggering RequestListeners and Targets. If the request is failed, beginning again will
      // restart the request, giving it another chance to complete. If the request is already
      // running, we can let it continue running without interruption.
      if (!Preconditions.checkNotNull(previous).isRunning()) {
        // Use the previous request rather than the new one to allow for optimizations like skipping
        // setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
        // that are done in the individual Request.
        previous.begin();
      }
      return target;
    }

    requestManager.clear(target);
    target.setRequest(request);
    requestManager.track(target, request);

    return target;
  }

首先通过buildRequest创建一个请求,创建完之后会将target原先所关联的请求断开,并设置为新的请求,然后通过requestManager.track()进行一些列的加载和处理显示操作

除了这种target,Glide还提供了两种Target类型SimpleTargetViewTarget,两者都继承于BaseTarget

        ViewTarget viewTarget = new ViewTarget<CircleImageView,Drawable>(mPersonIcon) {
            @Override
            public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                mPersonIcon.setImageDrawable(resource);
            }
        };
        Glide.with(mContext).load(url).into(viewTarget);
        SimpleTarget<Drawable> simpleTarget = new SimpleTarget<Drawable>() {
            @Override
            public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                mPersonZCodeImg.setImageDrawable(resource);
            }
        };
        Glide.with(mContext).load(url).into(simpleTarget);

看上去两者的调用都是非常的相似,SimpleTarget只是一个简单的Target,只要请求成功就展示;而ViewTarget从泛型上来说比Simple多一个,这个多出来的泛型也只是对入参的类型进行限定,不一定是Imageview可以是任务的View或是ViewGroup,传入目标view的意义则是重新计算view的大小,然后对图片进行处理显示

  • apply
    apply是用来传入目标view或者加载图片的配置信息的比说如指定宽高、占位图、错误展示图、view和图片的比例关系等。
  • listener
    listener是用来监听请求结果的,失败会返回异常信息,成功则会返回指定类型的图片
  • thumbnail
    加载缩略图

相关文章

网友评论

      本文标题:Glide4.0x源码浅析(二)

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