栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Glide设计模式之建造者(builder)模式1【GlideBuilder】

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Glide设计模式之建造者(builder)模式1【GlideBuilder】

Glide多种组合使用方式记录–没有全部亲测,大家可以根据实际需要选用
Glide设计模式之建造者(builder)模式1【GlideBuilder】
Glide设计模式之建造者(builder)模式2【RequestBuilder】
Glide设计模式之建造者(builder)模式3【RequestOptions】【baseRequestOptions】
Glide设计模式之建造者(builder)模式4总结【MemorySizeCalculator】【GlideExecutor】【PreFillType】【LazyHeaders】

官方定义

The intent of the Builder design pattern is to separate the
construction of a complex object from its representation. By doing so
the same construction process can create different representations.
将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示

场景描述

类的构造参数比较多,建议大于4个且这些参数大部分都是可选参数。即可考虑建造者模式

Glide.with(myFragment).load(url).centerCrop().placeholder(R.drawable.loading_spinner) .into(myImageView);

这个用法看上去参数就比较多。还要在单例模式进行创建的时候
主要是看com.bumptech.glide.GlideBuilder 这个是进行建造创建Glide的对象的建造者。先看build方法如下:

com.bumptech.glide.GlideBuilder

 @NonNull
  Glide build(@NonNull Context context) {
    if (sourceExecutor == null) {
      sourceExecutor = GlideExecutor.newSourceExecutor();
    }

    if (diskCacheExecutor == null) {
      diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
    }

    if (animationExecutor == null) {
      animationExecutor = GlideExecutor.newAnimationExecutor();
    }

    if (memorySizeCalculator == null) {
      memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
    }

    if (connectivityMonitorFactory == null) {
      connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
    }

    if (bitmapPool == null) {
      int size = memorySizeCalculator.getBitmapPoolSize();
      if (size > 0) {
        bitmapPool = new LruBitmapPool(size);
      } else {
        bitmapPool = new BitmapPoolAdapter();
      }
    }

    if (arrayPool == null) {
      arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
    }

    if (memoryCache == null) {
      memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
    }

    if (diskCacheFactory == null) {
      diskCacheFactory = new InternalCacheDiskCacheFactory(context);
    }

    if (engine == null) {
      engine =
          new Engine(
              memoryCache,
              diskCacheFactory,
              diskCacheExecutor,
              sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor(),
              animationExecutor,
              isActiveResourceRetentionAllowed);
    }

    if (defaultRequestListeners == null) {
      defaultRequestListeners = Collections.emptyList();
    } else {
      defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
    }

    GlideExperiments experiments = glideExperimentsBuilder.build();
    RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory, experiments);

    return new Glide(
        context,
        engine,
        memoryCache,
        bitmapPool,
        arrayPool,
        requestManagerRetriever,
        connectivityMonitorFactory,
        logLevel,
        defaultRequestOptionsFactory,
        defaultTransitionOptions,
        defaultRequestListeners,
        experiments);
  }

目测数了一下有12个默认参数,而且大部分是可选和可自定义的。

com.bumptech.glide.GlideBuilder的参数列表
private final Map, TransitionOptions> defaultTransitionOptions = new ArrayMap<>();
  private final GlideExperiments.Builder glideExperimentsBuilder = new GlideExperiments.Builder();
  private Engine engine;
  private BitmapPool bitmapPool;
  private ArrayPool arrayPool;
  private MemoryCache memoryCache;
  private GlideExecutor sourceExecutor;
  private GlideExecutor diskCacheExecutor;
  private DiskCache.Factory diskCacheFactory;
  private MemorySizeCalculator memorySizeCalculator;
  private ConnectivityMonitorFactory connectivityMonitorFactory;
  private int logLevel = Log.INFO;
  private RequestOptionsFactory defaultRequestOptionsFactory =
      new RequestOptionsFactory()。。。;
  @Nullable private RequestManagerFactory requestManagerFactory;
  private GlideExecutor animationExecutor;
  private boolean isActiveResourceRetentionAllowed;
  @Nullable private List> defaultRequestListeners;

可配置的属性有:

 
	设置 BitmapPool(可参考附录1)实现使用
	存储和检索复用的Bitmaps。
  @NonNull
  public GlideBuilder setBitmapPool(@Nullable BitmapPool bitmapPool) {
。。。
  
  @NonNull
   根据需要检索复用
   设置{@link ArrayPool(可参考附录1)}实现来允许存储可变大小的数组和
  public GlideBuilder setArrayPool(@Nullable ArrayPool arrayPool) {
。。。

  // Public API.
  @SuppressWarnings("WeakerAccess")
  @NonNull
设置 com.bumptech.glide.load.engine.cache.MemoryCache(可参考附录1)实现存储com.bumptech.glide.load.engine.Resource(可参考附录1) 或者当前未被使用Resource
  public GlideBuilder setMemoryCache(@Nullable MemoryCache memoryCache) {
。。。

   设置DiskCache.Factory(可参考附录1)接口实现来使用DiskCache(可参考附录1)的构造对象。用于存储资源数据到磁盘
   参数:diskCacheFactory 要使用的磁盘缓存工厂(所以下一篇是工厂模式,嘻嘻)
  // Public API.
  @SuppressWarnings("WeakerAccess")
  @NonNull
  public GlideBuilder setDiskCache(@Nullable DiskCache.Factory diskCacheFactory) {
。。。
 
   设置GlideExecutor(可参考附录1)用于检索不在缓存中的资源。
   线程数默认为设备上可用的核数,最大为4
   默认使用GlideExecutor#newSourceExecutor()方法,也可以指定线程池执行
   参数 service要使用的ExecutorService。
   **此方法已弃用**
   @Deprecated
  public GlideBuilder setResizeExecutor(@Nullable GlideExecutor service) {
  	return setSourceExecutor(service);
  }
。。。
 
   同setResizeExecutor是一样的作用。一般是兼容版本用的
  // Public API.
  @SuppressWarnings("WeakerAccess")
  @NonNull
  public GlideBuilder setSourceExecutor(@Nullable GlideExecutor service) {
。。。
 
   设置GlideExecutor(可参考附录1)用于检索当前在Glide的磁盘缓存中的资源
   默认为单个线程,这通常是内存使用、jank和的最佳组合 性能,甚至在高端设备上。
   默认使用GlideExecutor#newDiskCacheExecutor()(可参考附录1),可指定磁盘缓存执行器。
  // Public API.
  @SuppressWarnings("WeakerAccess")
  @NonNull
  public GlideBuilder setDiskCacheExecutor(@Nullable GlideExecutor service) {
。。。
  
   设置GlideExecutor(可参考附录1)用于加载动画图像帧,特别是GifDrawables
   默认为一个或两个线程,这取决于可用内核的数量。
   默认使用GlideExecutor#newAnimationExecutor()(可参考附录1)方法,可自定义选用动画执行器。
  // Public API.
  @SuppressWarnings("WeakerAccess")
  @NonNull
  public GlideBuilder setAnimationExecutor(@Nullable GlideExecutor service) {
  。。。
   
   设置默认的RequestOptions(可参考附录1)使用的所有加载的应用程序
   应用额外的选项与RequestBuilder(可参考附录1)#apply(baseRequestOptions)将
   覆盖这里设置的默认值。
  public GlideBuilder setDefaultRequestOptions(@Nullable final RequestOptions requestOptions) {
。。。

   为默认的RequestOptions设置一个工厂,用于应用程序的所有加载,并返回这个GlideBuilder。
   这个工厂不会每次加载都调用。相反,它会被调用几次并记住。对于每个新加载这个工厂再次被调用这样就不安全了。
   应用其他的选项将覆盖默认设置的RequestBuilder#apply(baseRequestOptions)
  @NonNull
  public GlideBuilder setDefaultRequestOptions(@NonNull RequestOptionsFactory factory) {
。。。
  
   设置默认TransitionOptions,以便在启动一个将使用给定Class加载资源的请求时使用。
只要这里应用的资源类可以从请求的资源类中分配,那么请求的资源类最好匹配这里应用的资源类,但这并不是必需的。例如,你可以为Drawable设置一个默认的转换,如果你随后开始请求特定的Drawable类型,如GifDrawable或BitmapDrawable,那么这个默认的转换将被使用。特定类型总是首选的,所以如果你注册一个默认的过渡,既可绘制和BitmapDrawable,然后启动一个BitmapDrawables的请求,你注册的BitmapDrawables的过渡将被使用。

注释解释起来挺费劲的。但是它的作用UI设计很喜欢:它是进行效果转换的。比如:圆角、透明度、高斯模糊也就是毛玻璃、圆头像等等图片裁剪处理的变换。
  // Public API.
  @SuppressWarnings("unused")
  @NonNull
  public  GlideBuilder setDefaultTransitionOptions(
。。。
 
   设置MemorySizeCalculator用于计算默认的MemoryCache和/或默认的BitmapPool BitmapPools的最大大小。
给定的MemorySizeCalculator不会影响通过setBitmapPool(BitmapPool)或setMemoryCache(MemoryCache)提供的自定义池或缓存。
  // Public API.
  @SuppressWarnings("unused")
  @NonNull
  设置MemorySizeCalculator用于计算默认的MemoryCache和/或默认的BitmapPool BitmapPools的最大大小。
  public GlideBuilder setMemorySizeCalculator(@NonNull MemorySizeCalculator.Builder builder) {
 		return setMemorySizeCalculator(builder.build());
  }
  

   设置MemorySizeCalculator用于计算默认的MemoryCache和/或默认的BitmapPool BitmapPools的最大大小。
给定的MemorySizeCalculator不会影响自定义池或通过提供的缓存
setBitmapPool (BitmapPool)或setMemoryCache (MemoryCache)。
  // Public API.
  @SuppressWarnings("WeakerAccess")
  @NonNull
  public GlideBuilder setMemorySizeCalculator(@Nullable MemorySizeCalculator calculator) {
。。。
  
   设置ConnectivityMonitorFactory来通知RequestManager连接事件。如果没有设置,将使用DefaultConnectivityMonitorFactory。

ConnectivityMonitorFactory:网络连接监视器工厂,又是一个【工厂模式】应用
  // Public API.
  @SuppressWarnings("unused")
  @NonNull
  public GlideBuilder setConnectivityMonitorFactory(@Nullable ConnectivityMonitorFactory factory) {
。。。
 
   从“日志”中设置一个日志级别常量,以指示所需的日志详细程度。
该级别必须是“VERBOSE”、“DEBUG”、“INFO”、“WARN”或“ERROR”中的一个。

Log#VERBOSE意味着每个请求将记录一行或多行,包括计时日志和失败。Log#DEBUG意味着每个成功的请求最多只会记录一行日志,包括计时日志,尽管可能会记录很多行失败的日志,包括多个完整的堆栈跟踪。Log#INFO意味着失败的加载将被记录,包括多个完整的堆栈跟踪,但是成功的加载将完全不被记录。Log#WARN表示只记录失败加载的摘要。日志#ERROR表示只会记录异常情况。所有日志将使用'Glide'标签记录。许多其他调试日志可以在单独的类中使用。这里提供的日志级别仅控制少量信息丰富且格式良好的日志。希望调试库的某些方面的用户可以在类的顶部查找单个的TAG变量,并使用adb shell setprop log.tag。TAG启用或禁用任何相关标签。
  // Public API.
  @SuppressWarnings("unused")
  @NonNull
  public GlideBuilder setLogLevel(int logLevel) {
。。。
 
   如果设置为true,允许Glide重新捕获加载到目标中的资源,这些资源随后被解除引用并被垃圾收集,而不被清除。默认值为false。Glide的资源重用系统是允许的,这意味着调用者可以将资源加载到Target中,然后从不清除Target。为此,Glide使用WeakReferences来跟踪属于target的尚未清除的资源。将此方法设置为true允许Glide也维护对底层资源的硬引用,以便如果Target被垃圾收集,Glide可以将底层资源返回到它的内存缓存中,以便后续请求不会意外地从磁盘或源重新加载资源。作为一个副作用,系统将花费更长的时间来垃圾收集底层资源,因为在硬引用被删除之前必须清除和处理弱引用。因此,将此方法设置为true可能会暂时增加应用程序的内存使用量。将此方法保留为默认false值将允许平台更快地垃圾收集资源,但如果调用者将资源加载到target中,将导致意外的内存缓存丢失。目标,但从未清除。如果你设置这个方法为真,你一定不能调用Bitmap#recycle()或改变任何由Glide返回的Bitmap。如果此方法被设置为false,回收或突变位图是低效的,但安全的,只要你不清除相应的目标用于加载位图。然而,如果你将此方法设置为true并回收或改变任何返回的位图或其他可变资源,Glide可能会恢复这些资源并试图在以后使用它们,导致崩溃、图形损坏或未定义的行为。
无论该方法被设置为什么值,在使用相应的资源时清除Targets总是一个好的实践。清除目标允许Glide最大化资源重用,最小化内存开销,最小化由边缘情况导致的意外行为。如果你使用RequestManager#clear(Target),调用Bitmap#recycle()或突变Bitmap不仅不安全,它也是完全不必要的,应该避免。在所有情况下,优先RequestManager#clear(Target)而不是Bitmap#recycle()。
  // Public API.
  @SuppressWarnings("unused")
  @NonNull
  public GlideBuilder setIsActiveResourceRetentionAllowed(
。。。

   添加一个全局RequestListener,将被添加到每个以Glide开始的请求。可以在RequestManager范围内添加多个RequestListener,也可以添加到单独的RequestBuilder中。RequestListener的调用顺序是按照添加的顺序进行的。即使先前的RequestListener从RequestListener#onLoadFailed(GlideException, Object, Target, boolean)或RequestListener#onResourceReady(Object, Object, Target, DataSource, boolean)返回true,它也不会阻止后续的RequestListener被调用。因为Glide请求可以为任意数量的单个资源类型启动,所以这里添加的任何侦听器都必须接受RequestListener#onResourceReady中的任何通用资源类型(Object, Object, Target, DataSource, boolean)。如果您必须将侦听器的行为基于资源类型,那么您将需要使用instanceof来做到这一点。不先使用instanceof检查就强制转换资源类型是不安全的。
  @NonNull
  public GlideBuilder addGlobalRequestListener(@NonNull RequestListener listener) {
。。。
 
设置为true使Glide为失败的请求填充GlideException.setOrigin(Exception)。
这个方法设置的异常不会被GlideException打印出来,只能通过RequestListener通过GlideException. getorigin()读取字段来查看。

这是一个实验性API,将来可能会被删除。
  public GlideBuilder setLogRequestOrigins(boolean isEnabled) {
。。。
Set to true to make Glide use ImageDecoder when decoding Bitmaps on Android P and higher.
Calls to this method on versions of Android less than Q are ignored. Although ImageDecoder was added in Android O a bug prevents it from scaling images with exif orientations until Q. See b/136096254.

Specifically ImageDecoder will be used in place of Downsampler and BitmapFactory to decode Bitmaps. GIFs, resources, and all other types of Drawables are not affected by this flag.

This flag is experimental and may be removed without deprecation in a future version.

When this flag is enabled, Bitmap's will not be re-used when decoding images, though they may still be used as part of Transformations because ImageDecoder does not support Bitmap re-use.

When this flag is enabled Downsampler.FIX_BITMAP_SIZE_TO_REQUESTED_DIMENSIONS is ignored. All other Downsampler flags are obeyed, although there may be subtle behavior differences because many options are subject to the whims of BitmapFactory and ImageDecoder which may not agree.
设置为true,使Glide使用ImageDecoder解码位图时,在Android P或更高。
在小于Q的Android版本上调用此方法将被忽略。尽管ImageDecoder在Android O中添加了一个bug,阻止它使用exif方向缩放图像直到q。

特别是ImageDecoder将被用来代替Downsampler和BitmapFactory来解码bitmap。gif、资源和所有其他类型的可绘制对象不受此标志的影响。

该标志是实验性的,在未来的版本中可能会被移除而不反对。

当这个标志被启用时,Bitmap的将不会在解码图像时被重用,尽管它们可能仍然被用作转换的一部分,因为ImageDecoder不支持Bitmap的重用。

当这个标志被启用时,Downsampler。FIX_BITMAP_SIZE_TO_REQUESTED_DIMENSIONS被忽略。所有其他的Downsampler标志是服从的,尽管有可能有细微的行为差异,因为许多选项是受BitmapFactory和ImageDecoder的影响可能不能用。
  public GlideBuilder setImageDecoderEnabledForBitmaps(boolean isEnabled) {
。。。
 
小计 

GlideBuilder作为配置构建Glide对象的核心,主要的业务流程从这里开始,理解了Glide的构建配置也就能更好的理解后面的应用配置和网络配置。
其设计理念包含了很多不错的实践。

  • 内存优化:bitmapPool、arrayPool、memoryCache;
  • 缓冲优化:memoryCache、diskCacheFactory。
  • CPU执行:sourceExecutor、diskCacheExecutor、memorySizeCalculator、animationExecutor;
  • 网络优化:connectivityMonitorFactory、defaultRequestOptionsFactory、requestManagerFactory

后期的Glide算法解析篇主要是围绕上面几方面进行的。本着拿来即用的原则。本人也会把其中能拿来用的使用形式归纳总结出来供大家使用。由于不涉及具体业务,也许不能直接用于项目上。但是其中关键部分和其结构就靠读者们思量着是否合用了。

一点感想

五六年前在使用Glide的时候觉得就这么一行应该不会太复杂。直到从设计模式试着解析并记录后才发现其中的高明和厉害之处。
之所以选择解析Glide开源项目也是因为觉得不会太难所以写几篇刷刷存在感。但深入之后才发现把复杂留给自己,把简洁的使用让给用户和访问者这其中的艰辛。我也将怀着敬畏之心。尽我所能把其中的设计优化适配等结构写清楚。
也请大家在最初设计和实现的过程中尽量从使用者的角度出发,从使用者环境出发考虑。不忘初心的写出更多很哇塞的功能模块。加油!

附录1 相关类说明 com.bumptech.glide.load.engine.cache.MemoryCache

An interface for adding and removing resources from an in memory
cache.

用于从内存缓存中添加和删除资源的接口。

com.bumptech.glide.load.engine.Resource

一种资源接口,它包装了特定的类型,以便它可以被合用和复用。
参数:可包装的资源类

com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool

An interface for a pool that allows users to reuse {@link
android.graphics.Bitmap} objects.

一个允许用户复用Bitmap 对象接口。

com.bumptech.glide.load.engine.bitmap_recycle.ArrayPool

Interface for an array pool that pools arrays of different types.

一个数组池接口,存储不同类型数组的池

com.bumptech.glide.load.engine.cache.DiskCache.Factory

An interface for lazily creating a disk cache.

接口功能延迟创建磁盘缓存

com.bumptech.glide.load.engine.cache.DiskCache

An interface for writing to and reading from a disk cache.

一种从磁盘缓存中写入和读取数据的接口。

com.bumptech.glide.load.engine.executor.GlideExecutor

A prioritized {@link ThreadPoolExecutor} for running jobs in Glide.

在Glide中自定义优先级的任务运行的线程池线程执行器

com.bumptech.glide.load.resource.gif.GifDrawable

An animated {@link android.graphics.drawable.Drawable} that plays the
frames of an animated GIF.

播放GIF动画帧的动画Drawable。

com.bumptech.glide.request.RequestOptions


@SuppressWarnings(“PMD.UseUtilityClass”)

Glide 提供类型独立可选项,用于自定义加载策略
Non-final允许Glide生成的类可以赋值给它们的非生成类。

com.bumptech.glide.request.baseRequestOptions
 

一个允许RequestOptions和RequestBuilder之间方法共享的基础对象。
个类不是一般使用的,可能随时更改
特定的子实现

com.bumptech.glide.Glide.RequestOptionsFactory
 

创建一个新的RequestOptions实例

com.bumptech.glide.RequestBuilder
 

一个泛型类,可以处理泛型资源类型的设置选项和启动加载
参数 将被交付给目标的资源类型

com.bumptech.glide.load.engine.cache.MemorySizeCalculator
 

一个计算器,试图智能决定缓存大小为给定的设备基于一些常量和设备屏幕密度,宽度和高度。

com.bumptech.glide.manager.ConnectivityMonitorFactory
 

一个工厂类,产生一个功能性的ConnectivityMonitor。

com.bumptech.glide.RequestManager
 

一个管理和启动Glide请求的课程。可以使用活动、片段和连接生命周期事件来智能地停止、启动和重新启动请求。通过实例化一个新对象来获取,或者利用内置的Activity和Fragment生命周期处理,使用静态的Glide。加载方法与你的Fragment或Activity。

com.bumptech.glide.manager.DefaultConnectivityMonitorFactory
 

一个工厂类,如果应用程序有ACCESS_NETWORK_STATE权限,它会生成一个功能性的ConnectivityMonitor;如果应用程序没有必要的权限,它会生成一个无操作的非功能性的ConnectivityMonitor。

com.bumptech.glide.manager.ConnectivityMonitor
An interface for monitoring network connectivity events.

监视网络连接事件的接口。

com.bumptech.glide.request.target.Target
 

一个接口,Glide可以将资源加载到该接口中,并在加载期间通知相关的生命周期事件。
这个类中的生命周期事件如下:
onLoadStarted
onResourceReady
onLoadCleared
onLoadFailed

典型的生命周期是onLoadStarted -> onResourceReady或onLoadFailed -> onLoadCleared。
然而,这并不能保证。如果资源在内存中,或者由于一个空模型对象而导致加载失败,onLoadStarted可能不会被调用。同样,如果目标从未被清除,onLoadCleared也可能永远不会被调用。有关具体方法的详细信息,请参阅文档。

  • @param 目标可以显示的资源类型。
com.bumptech.glide.request.RequestListener
 

一个类,用于在图像加载时监视请求的状态。

如果RequestListener被添加到RequestBuilder#submit(), RequestBuilder#submit(int, int)或RequestBuilder#提交(int, int)或RequestBuilder#into(int, int)的请求中,这个接口中的所有方法将从后台线程被调用。这些方法不再将结果发布回主线程,以避免不必要的线程交互和相应的延迟。不过,作为附带影响,添加到这些请求的侦听器不再在主线程上调用。RequestListeners添加到RequestBuilder#into(Target)或RequestBuilder#into(ImageView)的请求将继续在主线程上被调用。

@param 正在加载的资源类型。

附录2 com.bumptech.glide.load.engine.GlideException extends Exception
 

一个异常,零或多个原因表明为什么在Glide加载失败

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号