官方定义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
小计
GlideBuilder作为配置构建Glide对象的核心,主要的业务流程从这里开始,理解了Glide的构建配置也就能更好的理解后面的应用配置和网络配置。
其设计理念包含了很多不错的实践。
- 内存优化:bitmapPool、arrayPool、memoryCache;
- 缓冲优化:memoryCache、diskCacheFactory。
- CPU执行:sourceExecutor、diskCacheExecutor、memorySizeCalculator、animationExecutor;
- 网络优化:connectivityMonitorFactory、defaultRequestOptionsFactory、requestManagerFactory
后期的Glide算法解析篇主要是围绕上面几方面进行的。本着拿来即用的原则。本人也会把其中能拿来用的使用形式归纳总结出来供大家使用。由于不涉及具体业务,也许不能直接用于项目上。但是其中关键部分和其结构就靠读者们思量着是否合用了。
一点感想五六年前在使用Glide的时候觉得就这么一行应该不会太复杂。直到从设计模式试着解析并记录后才发现其中的高明和厉害之处。
之所以选择解析Glide开源项目也是因为觉得不会太难所以写几篇刷刷存在感。但深入之后才发现把复杂留给自己,把简洁的使用让给用户和访问者这其中的艰辛。我也将怀着敬畏之心。尽我所能把其中的设计优化适配等结构写清楚。
也请大家在最初设计和实现的过程中尽量从使用者的角度出发,从使用者环境出发考虑。不忘初心的写出更多很哇塞的功能模块。加油!
An interface for adding and removing resources from an in memory
cache.
用于从内存缓存中添加和删除资源的接口。
com.bumptech.glide.load.engine.Resource一种资源接口,它包装了特定的类型,以便它可以被合用和复用。
参数:可包装的资源类
An interface for a pool that allows users to reuse {@link
android.graphics.Bitmap} objects.
一个允许用户复用Bitmap 对象接口。
com.bumptech.glide.load.engine.bitmap_recycle.ArrayPoolInterface for an array pool that pools arrays of different types.
一个数组池接口,存储不同类型数组的池
com.bumptech.glide.load.engine.cache.DiskCache.FactoryAn interface for lazily creating a disk cache.
接口功能延迟创建磁盘缓存
com.bumptech.glide.load.engine.cache.DiskCacheAn interface for writing to and reading from a disk cache.
一种从磁盘缓存中写入和读取数据的接口。
com.bumptech.glide.load.engine.executor.GlideExecutorA prioritized {@link ThreadPoolExecutor} for running jobs in Glide.
在Glide中自定义优先级的任务运行的线程池线程执行器
com.bumptech.glide.load.resource.gif.GifDrawableAn 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生成的类可以赋值给它们的非生成类。
一个允许RequestOptions和RequestBuilder之间方法共享的基础对象。
个类不是一般使用的,可能随时更改
特定的子实现
创建一个新的RequestOptions实例
com.bumptech.glide.RequestBuilder一个泛型类,可以处理泛型资源类型的设置选项和启动加载
参数 将被交付给目标的资源类型
一个计算器,试图智能决定缓存大小为给定的设备基于一些常量和设备屏幕密度,宽度和高度。
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.ConnectivityMonitorAn interface for monitoring network connectivity events.
监视网络连接事件的接口。
com.bumptech.glide.request.target.Target一个接口,Glide可以将资源加载到该接口中,并在加载期间通知相关的生命周期事件。
这个类中的生命周期事件如下:
onLoadStarted
onResourceReady
onLoadCleared
onLoadFailed
典型的生命周期是onLoadStarted -> onResourceReady或onLoadFailed -> onLoadCleared。
然而,这并不能保证。如果资源在内存中,或者由于一个空模型对象而导致加载失败,onLoadStarted可能不会被调用。同样,如果目标从未被清除,onLoadCleared也可能永远不会被调用。有关具体方法的详细信息,请参阅文档。
*
- @param 目标可以显示的资源类型。
一个类,用于在图像加载时监视请求的状态。
如果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加载失败



