杨说:Glide 4.11.0 配置请求参数

2,179 阅读5分钟

上一章说到了Glide第一步配置Glide.with(context),返回统一的RequestManager,这个时候这个RequestManager具备了,生命周期监控的能力,详情请看 杨说:Glide 生命周期监听 这里我们开始将第二步,请求的配置

Glide.with(fragment)
    .load(url)
    .into(imageView);

目录

一、创建RequestBuilder
二、配置占位符
三、配置选项
四、过渡选项
五、缩略图
六、变换
七、缓存
八、总结

一 创建RequestBuilder

with()方法返回RequestManager后调用load(url)方法,这个方法有很多重载方法

RequestManager.java

public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {
    return asDrawable().load(bitmap);
  }

public RequestBuilder<Drawable> load(@Nullable Drawable drawable) {
    return asDrawable().load(drawable);
  }

public RequestBuilder<Drawable> load(@Nullable String string) {
    return asDrawable().load(string);
  }
  
public RequestBuilder<Drawable> load(@Nullable Uri uri) {
    return asDrawable().load(uri);
  }
  
public RequestBuilder<Drawable> load(@Nullable File file) {
    return asDrawable().load(file);
  }
  
public RequestBuilder<Drawable> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
    return asDrawable().load(resourceId);
  }
  
public RequestBuilder<Drawable> load(@Nullable URL url) {
    return asDrawable().load(url);
  }
  
public RequestBuilder<Drawable> load(@Nullable byte[] model) {
    return asDrawable().load(model);
  }
  
public RequestBuilder<Drawable> load(@Nullable Object model) {
    return asDrawable().load(model);
  }

他们都是统一调用了asDrawable(),传入需要

public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
  }
  
public <ResourceType> RequestBuilder<ResourceType> as(
      @NonNull Class<ResourceType> resourceClass) {
    //这里创建了RequestBuilder,RequestBuilder使用建造者模式构建请求的所有参数
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }

创建RequestBuilder的代码

RequestBuilder.java

 protected RequestBuilder(
      @NonNull Glide glide,
      RequestManager requestManager,
      Class<TranscodeType> transcodeClass,
      Context context) {
    this.glide = glide;
    this.requestManager = requestManager;
    this.transcodeClass = transcodeClass;
    this.context = context;
    this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass);
    this.glideContext = glide.getGlideContext();

    initRequestListeners(requestManager.getDefaultRequestListeners());
    apply(requestManager.getDefaultRequestOptions());
  }

requestManager.getDefaultRequestListeners()获取的是glide外部配置的RequestListeners,他是在创建RequestManager的时候被赋值的,CopyOnWriteArrayList是线程安全的List通过读写锁保证线程安全

RequestManager.java

 RequestManager(
      Glide glide,
      Lifecycle lifecycle,
      RequestManagerTreeNode treeNode,
      RequestTracker requestTracker,
      ConnectivityMonitorFactory factory,
      Context context) {
    ····
    defaultRequestListeners =
        new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
    ···
  }

initRequestListeners(requestManager.getDefaultRequestListeners());将外部配置的RequestListener添加到RequestBuilder监听列表中

RequestBuilder.java

private void initRequestListeners(List<RequestListener<Object>> requestListeners) {
    for (RequestListener<Object> listener : requestListeners) {
      addListener((RequestListener<TranscodeType>) listener);
    }
  }
  
public RequestBuilder<TranscodeType> addListener(
      @Nullable RequestListener<TranscodeType> requestListener) {
    if (requestListener != null) {
      if (this.requestListeners == null) {
        this.requestListeners = new ArrayList<>();
      }
      this.requestListeners.add(requestListener);
    }
    return this;
  }

requestManager.getDefaultRequestOptions(); 获取请求配置,他也是在创建RequestManager的时候被赋值的,通过原型模式复制请求选项

RequestManager.java

 RequestManager(
      Glide glide,
      Lifecycle lifecycle,
      RequestManagerTreeNode treeNode,
      RequestTracker requestTracker,
      ConnectivityMonitorFactory factory,
      Context context) {
    ····
    setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
    ···
  }

 protected synchronized void setRequestOptions(@NonNull RequestOptions toSet) {
    requestOptions = toSet.clone().autoClone();
  }

BaseRequestOption.java

public T clone() {
    try {
      BaseRequestOptions<?> result = (BaseRequestOptions<?>) super.clone();
      result.options = new Options();
      result.options.putAll(options);
      result.transformations = new CachedHashCodeArrayMap<>();
      result.transformations.putAll(transformations);
      result.isLocked = false;
      result.isAutoCloneEnabled = false;
      return (T) result;
    } catch (CloneNotSupportedException e) {
      throw new RuntimeException(e);
    }
  }

apply(requestManager.getDefaultRequestOptions()); 将请求选项添加到RequestBuilder中

RequestBuilder.java

public RequestBuilder<TranscodeType> apply(@NonNull BaseRequestOptions<?> requestOptions) {
    Preconditions.checkNotNull(requestOptions);
    return super.apply(requestOptions);
  }
BaseRequestOptions.java 它是RequestBuilder的父类

 public T apply(@NonNull BaseRequestOptions<?> o) {
    if (isAutoCloneEnabled) {
      return clone().apply(o);
    }
    BaseRequestOptions<?> other = o;
   ···
   //上面是系列的赋值操作,使用的是位计算方式
    fields |= other.fields;
    //添加到选项中
    options.putAll(other.options);

    return selfOrThrowIfLocked();
  }

创建RequestBuilder就可以配置Glide的所有的配置了比如图形的变换,是否缓存等

二 配置占位符

 Glide.with(this)
            .load(url)
            .placeholder(R.drawable.holder) //正在请求时被展示,没有设置error和,url为null也展示
            .error(R.drawable.error) //出错时展示,没有设置fallback,URL为null展示
            .fallback(R.drawable.fallback) //fallback是URL为null的时候展示
            .into(iv_activity)

placeholder(R.drawable.holder)

BaseRequestOptions.java

//设置图片选项
public T placeholder(@Nullable Drawable drawable) {
    if (isAutoCloneEnabled) {
      return clone().placeholder(drawable);
    }
	//复制placeholderDrawable
    this.placeholderDrawable = drawable;
    fields |= PLACEHOLDER;

    placeholderId = 0;
    fields &= ~PLACEHOLDER_ID;

    return selfOrThrowIfLocked();
  }
  
private T selfOrThrowIfLocked() {
    if (isLocked) {
      throw new IllegalStateException("You cannot modify locked T, consider clone()");
    }
    //返回当前对象
    return self();
  }

error(R.drawable.error)

BaseRequestOptions.java

public T error(@Nullable Drawable drawable) {
    if (isAutoCloneEnabled) {
      return clone().error(drawable);
    }
	//errorPlaceholder 赋值errorPlaceholder
    this.errorPlaceholder = drawable;
    fields |= ERROR_PLACEHOLDER;

    this.errorId = 0;
    fields &= ~ERROR_ID;
	//返回当前对象
    return selfOrThrowIfLocked();
  }

fallback(R.drawable.fallback)

BaseRequestOptions.java

public T fallback(@Nullable Drawable drawable) {
    if (isAutoCloneEnabled) {
      return clone().fallback(drawable);
    }
	//fallbackDrawable 赋值fallbackDrawable
    this.fallbackDrawable = drawable;
    fields |= FALLBACK;

    fallbackId = 0;
    fields &= ~FALLBACK_ID;
	//返回当前对象
    return selfOrThrowIfLocked();
  }

三 配置选项

如果需要统一配置的话,那可以统一设置选项然后设置到Glide中

 var option = RequestOptions().placeholder(ColorDrawable(Color.BLACK))
            .error(ColorDrawable(Color.BLUE))
            .fallback(ColorDrawable(Color.RED))
        Glide.with(this)
            .load(url)
            .apply(option)
            .into(iv_activity)

apply(option),接收外部设置的参数,建造者模式构建RequestOptions对象

RequestBuilder.java

public RequestBuilder<TranscodeType> apply(@NonNull BaseRequestOptions<?> requestOptions) {
    Preconditions.checkNotNull(requestOptions);
    return super.apply(requestOptions);
  }

给所有的参数赋值

BaseRequestOptions.java

public T apply(@NonNull BaseRequestOptions<?> o) {
    ····		

    fields |= other.fields;
    options.putAll(other.options);

    return selfOrThrowIfLocked();
  }

四 过渡选项

Glide.with(this)
            .load(uri)
            .transition(DrawableTransitionOptions())
            .into(iv_activity)

transition(DrawableTransitionOptions())直接赋值给transitionOptions

RequestBuilder.java

public RequestBuilder<TranscodeType> transition(
      @NonNull TransitionOptions<?, ? super TranscodeType> transitionOptions) {
    this.transitionOptions = Preconditions.checkNotNull(transitionOptions);
    isDefaultTransitionOptionsSet = false;
    return this;
  }

五 缩略图

 Glide.with(this)
            .load(uri)
            .thumbnail(Glide.with(this).load(url))
            .into(iv_activity)

thumbnail(Glide.with(this).load(url))接收一个RequestBuilder尺寸比要下载的图片小,加载速度会比大图快

RequestBuilder.java

public RequestBuilder<TranscodeType> thumbnail(
      @Nullable RequestBuilder<TranscodeType> thumbnailRequest) {
    this.thumbnailBuilder = thumbnailRequest;

    return this;
  }

六 变换

6.1 单个的变换

 Glide.with(this)
            .load(uri)
            .transform(CircleCrop())
            .into(iv_activity)

获取资源并修改它,然后返回被修改后的资源。transform(CircleCrop())接收一个Transformation接口类型的参数,gilde给我们提供了默认的一个实现类型,比如CircleCrop(),如果我们需要自定义可以继承BitmapTransformation(),需要复写equals(),hashCode(),updateDiskCacheKey()

BaseRequestOptions.java

public T transform(@NonNull Transformation<Bitmap> transformation) {
    return transform(transformation, /*isRequired=*/ true);
  }
  
T transform(@NonNull Transformation<Bitmap> transformation, boolean isRequired) {
    if (isAutoCloneEnabled) {
      return clone().transform(transformation, isRequired);
    }
	//创建了一个DrawableTransformation
    DrawableTransformation drawableTransformation =
        new DrawableTransformation(transformation, isRequired);
    //这里分别创建了四个转换
    transform(Bitmap.class, transformation, isRequired);
    transform(Drawable.class, drawableTransformation, isRequired);
    // TODO: remove BitmapDrawable decoder and this transformation.
    // Registering as BitmapDrawable is simply an optimization to avoid some iteration and
    // isAssignableFrom checks when obtaining the transformation later on. It can be removed without
    // affecting the functionality.
    transform(BitmapDrawable.class, drawableTransformation.asBitmapDrawable(), isRequired);
    transform(GifDrawable.class, new GifDrawableTransformation(transformation), isRequired);
    return selfOrThrowIfLocked();
  }

transform(Bitmap.class, transformation, isRequired);四个变换调动的都是一个方法,分别把变换添加到transformations中,这是一个Map,复制后返回RequestBuilder

BaseRequestOptions.java

<Y> T transform(
      @NonNull Class<Y> resourceClass,
      @NonNull Transformation<Y> transformation,
      boolean isRequired) {
    if (isAutoCloneEnabled) {
      return clone().transform(resourceClass, transformation, isRequired);
    }

    Preconditions.checkNotNull(resourceClass);
    Preconditions.checkNotNull(transformation);
    transformations.put(resourceClass, transformation);
    fields |= TRANSFORMATION;
    isTransformationAllowed = true;
    fields |= TRANSFORMATION_ALLOWED;
    // Always set to false here. Known scale only transformations will call this method and then
    // set isScaleOnlyOrNoTransform to true immediately after.
    isScaleOnlyOrNoTransform = false;
    if (isRequired) {
      fields |= TRANSFORMATION_REQUIRED;
      isTransformationRequired = true;
    }
    return selfOrThrowIfLocked();
  }

6.2 多重变换

BaseRequestOptions.java

public T transform(@NonNull Transformation<Bitmap>... transformations) {
    if (transformations.length > 1) {
 	  // 传参大于一个
      return transform(new MultiTransformation<>(transformations), /*isRequired=*/ true);
    } else if (transformations.length == 1) {
      //传参1个跟调用单个变换方法
      return transform(transformations[0]);
    } else {
      return selfOrThrowIfLocked();
    }
  }

transform(new MultiTransformation<>(transformations), /isRequired=/ true); 传参大于一个使用MultiTransformation变换,变换的时候会依次进程变换。然后继续调用单个变换方法

MultiTransformation.java

public Resource<T> transform(
      @NonNull Context context, @NonNull Resource<T> resource, int outWidth, int outHeight) {
    Resource<T> previous = resource;

    for (Transformation<T> transformation : transformations) {
      Resource<T> transformed = transformation.transform(context, previous, outWidth, outHeight);
      if (previous != null && !previous.equals(resource) && !previous.equals(transformed)) {
        previous.recycle();
      }
      previous = transformed;
    }
    return previous;
  }

七 缓存

设置缓存策略

Glide.with(this)
            .load(uri)
            .diskCacheStrategy(DiskCacheStrategy.ALL)
            .into(iv_activity)

diskCacheStrategy(DiskCacheStrategy.ALL) DiskCacheStrategy.ALL 使用策略模式,定义不同的策略


public abstract class DiskCacheStrategy {

  /**
   * Caches remote data with both {@link #DATA} and {@link #RESOURCE}, and local data with {@link
   * #RESOURCE} only.
   */
  public static final DiskCacheStrategy ALL =
    ···

  /** Saves no data to cache. */
  public static final DiskCacheStrategy NONE =
     ···

  /** Writes retrieved data directly to the disk cache before it's decoded. */
  public static final DiskCacheStrategy DATA =
      ···

  /** Writes resources to disk after they've been decoded. */
  public static final DiskCacheStrategy RESOURCE =
      ···

  /**
   * Tries to intelligently choose a strategy based on the data source of the {@link
   * com.bumptech.glide.load.data.DataFetcher} and the {@link
   * com.bumptech.glide.load.EncodeStrategy} of the {@link com.bumptech.glide.load.ResourceEncoder}
   * (if an {@link com.bumptech.glide.load.ResourceEncoder} is available).
   */
  public static final DiskCacheStrategy AUTOMATIC =
     ····

  /**
   * Returns true if this request should cache the original unmodified data.
   *
   * @param dataSource Indicates where the data was originally retrieved.
   */
  public abstract boolean isDataCacheable(DataSource dataSource);

  /**
   * Returns true if this request should cache the final transformed resource.
   *
   * @param isFromAlternateCacheKey {@code true} if the resource we've decoded was loaded using an
   *     alternative, rather than the primary, cache key.
   * @param dataSource Indicates where the data used to decode the resource was originally
   *     retrieved.
   * @param encodeStrategy The {@link EncodeStrategy} the {@link
   *     com.bumptech.glide.load.ResourceEncoder} will use to encode the resource.
   */
  public abstract boolean isResourceCacheable(
      boolean isFromAlternateCacheKey, DataSource dataSource, EncodeStrategy encodeStrategy);

  /** Returns true if this request should attempt to decode cached resource data. */
  public abstract boolean decodeCachedResource();

  /** Returns true if this request should attempt to decode cached source data. */
  public abstract boolean decodeCachedData();
}

将策略赋值给diskCacheStrategy

BaseRequestOptions

public T diskCacheStrategy(@NonNull DiskCacheStrategy strategy) {
    if (isAutoCloneEnabled) {
      return clone().diskCacheStrategy(strategy);
    }
    this.diskCacheStrategy = Preconditions.checkNotNull(strategy);
    fields |= DISK_CACHE_STRATEGY;

    return selfOrThrowIfLocked();
  }

跳过缓存

Glide.with(this)
            .load(uri)
            .skipMemoryCache(true)
            .into(iv_activity)
BaseRequestOptions.java
            
public T skipMemoryCache(boolean skip) {
    if (isAutoCloneEnabled) {
      return clone().skipMemoryCache(true);
    }

    this.isCacheable = !skip;
    fields |= IS_CACHEABLE;

    return selfOrThrowIfLocked();
  }

八 总结

Glide通过建造者模式,和原型模式,配置各个请求参数构建RequestBuilder,也可以通过创建RequestOptions统一配置,在这步只是简单的赋值,并没有做实际的请求,转换。 Glide的配置也可能通过注解的方式设置,比如更换图片网络库,默认HttpURLConnection