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<Class<?>, 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<RequestListener<Object>> defaultRequestListeners;
可配置的属性有:
/**
* Sets the {@link com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool} implementation to use
* to store and retrieve reused {@link android.graphics.Bitmap}s.
*
* @param bitmapPool The pool to use.
* @return This builder.
*/
设置 BitmapPool(可参考附录1)实现使用
存储和检索复用的Bitmaps。
@NonNull
public GlideBuilder setBitmapPool(@Nullable BitmapPool bitmapPool) {
。。。
/**
* Sets the {@link ArrayPool} implementation to allow variable sized arrays to be stored and
* retrieved as needed.
*
* @param arrayPool The pool to use.
* @return This builder.
*/
@NonNull
根据需要检索复用
设置{@link ArrayPool(可参考附录1)}实现来允许存储可变大小的数组和
public GlideBuilder setArrayPool(@Nullable ArrayPool arrayPool) {
。。。
/**
* Sets the {@link com.bumptech.glide.load.engine.cache.MemoryCache} implementation to store
* {@link com.bumptech.glide.load.engine.Resource}s that are not currently in use.
*
* @param memoryCache The cache to use.
* @return This builder.
*/
// 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) {
。。。
/**
* Sets the {@link com.bumptech.glide.load.engine.cache.DiskCache.Factory} implementation to use
* to construct the {@link com.bumptech.glide.load.engine.cache.DiskCache} to use to store {@link
* com.bumptech.glide.load.engine.Resource} data on disk.
*
* @param diskCacheFactory The disk cache factory to use.
* @return This builder.
*/
设置DiskCache.Factory(可参考附录1)接口实现来使用DiskCache(可参考附录1)的构造对象。用于存储资源数据到磁盘
参数:diskCacheFactory 要使用的磁盘缓存工厂(所以下一篇是工厂模式,嘻嘻)
// Public API.
@SuppressWarnings("WeakerAccess")
@NonNull
public GlideBuilder setDiskCache(@Nullable DiskCache.Factory diskCacheFactory) {
。。。
/**
* Sets the {@link GlideExecutor} to use when retrieving {@link
* com.bumptech.glide.load.engine.Resource}s that are not already in the cache.
*
* <p>The thread count defaults to the number of cores available on the device, with a maximum of
* 4.
*
* <p>Use the {@link GlideExecutor#newSourceExecutor()} methods if you'd like to specify options
* for the source executor.
*
* @param service The ExecutorService to use.
* @return This builder.
* @see #setDiskCacheExecutor(GlideExecutor)
* @see GlideExecutor
* @deprecated Use {@link #setSourceExecutor(GlideExecutor)}
*/
设置GlideExecutor(可参考附录1)用于检索不在缓存中的资源。
线程数默认为设备上可用的核数,最大为4
默认使用GlideExecutor#newSourceExecutor()方法,也可以指定线程池执行
参数 service要使用的ExecutorService。
**此方法已弃用**
@Deprecated
public GlideBuilder setResizeExecutor(@Nullable GlideExecutor service) {
return setSourceExecutor(service);
}
。。。
/**
* Sets the {@link GlideExecutor} to use when retrieving {@link
* com.bumptech.glide.load.engine.Resource}s that are not already in the cache.
*
* <p>The thread count defaults to the number of cores available on the device, with a maximum of
* 4.
*
* <p>Use the {@link GlideExecutor#newSourceExecutor()} methods if you'd like to specify options
* for the source executor.
*
* @param service The ExecutorService to use.
* @return This builder.
* @see #setDiskCacheExecutor(GlideExecutor)
* @see GlideExecutor
*/
同setResizeExecutor是一样的作用。一般是兼容版本用的
// Public API.
@SuppressWarnings("WeakerAccess")
@NonNull
public GlideBuilder setSourceExecutor(@Nullable GlideExecutor service) {
。。。
/**
* Sets the {@link GlideExecutor} to use when retrieving {@link
* com.bumptech.glide.load.engine.Resource}s that are currently in Glide's disk caches.
*
* <p>Defaults to a single thread which is usually the best combination of memory usage, jank, and
* performance, even on high end devices.
*
* <p>Use the {@link GlideExecutor#newDiskCacheExecutor()} if you'd like to specify options for
* the disk cache executor.
*
* @param service The {@link GlideExecutor} to use.
* @return This builder.
* @see #setSourceExecutor(GlideExecutor)
* @see GlideExecutor
*/
设置GlideExecutor(可参考附录1)用于检索当前在Glide的磁盘缓存中的资源
默认为单个线程,这通常是内存使用、jank和的最佳组合 性能,甚至在高端设备上。
默认使用GlideExecutor#newDiskCacheExecutor()(可参考附录1),可指定磁盘缓存执行器。
// Public API.
@SuppressWarnings("WeakerAccess")
@NonNull
public GlideBuilder setDiskCacheExecutor(@Nullable GlideExecutor service) {
。。。
/**
* Sets the {@link GlideExecutor} to use when loading frames of animated images and particularly
* of {@link com.bumptech.glide.load.resource.gif.GifDrawable}s.
*
* <p>Defaults to one or two threads, depending on the number of cores available.
*
* <p>Use the {@link GlideExecutor#newAnimationExecutor()} methods if you'd like to specify
* options for the animation executor.
*
* @param service The {@link GlideExecutor} to use.
* @return This builder.
*/
设置GlideExecutor(可参考附录1)用于加载动画图像帧,特别是GifDrawables
默认为一个或两个线程,这取决于可用内核的数量。
默认使用GlideExecutor#newAnimationExecutor()(可参考附录1)方法,可自定义选用动画执行器。
// Public API.
@SuppressWarnings("WeakerAccess")
@NonNull
public GlideBuilder setAnimationExecutor(@Nullable GlideExecutor service) {
。。。
/**
* Sets the default {@link RequestOptions} to use for all loads across the app.
*
* <p>Applying additional options with {@link RequestBuilder#apply(BaseRequestOptions)} will
* override defaults set here.
*
* @see #setDefaultRequestOptions(RequestOptionsFactory)
* @param requestOptions The options to use by default.
* @return This builder.
*/
设置默认的RequestOptions(可参考附录1)使用的所有加载的应用程序
应用额外的选项与RequestBuilder(可参考附录1)#apply(BaseRequestOptions)将
覆盖这里设置的默认值。
public GlideBuilder setDefaultRequestOptions(@Nullable final RequestOptions requestOptions) {
。。。
/**
* Sets a factory for the default {@link RequestOptions} to use for all loads across the app and
* returns this {@code GlideBuilder}.
*
* <p>This factory will <em>NOT</em> be called once per load. Instead it will be called a handful
* of times and memoized. It's not safe to assume that this factory will be called again for every
* new load.
*
* <p>Applying additional options with {@link RequestBuilder#apply(BaseRequestOptions)} will
* override defaults set here.
*
* @see #setDefaultRequestOptions(RequestOptionsFactory)
*/
为默认的RequestOptions设置一个工厂,用于应用程序的所有加载,并返回这个GlideBuilder。
这个工厂不会每次加载都调用。相反,它会被调用几次并记住。对于每个新加载这个工厂再次被调用这样就不安全了。
应用其他的选项将覆盖默认设置的RequestBuilder#apply(BaseRequestOptions)
@NonNull
public GlideBuilder setDefaultRequestOptions(@NonNull RequestOptionsFactory factory) {
。。。
/**
* Sets the default {@link TransitionOptions} to use when starting a request that will load a
* resource with the given {@link Class}.
*
* <p>It's preferable but not required for the requested resource class to match the resource
* class applied here as long as the resource class applied here is assignable from the requested
* resource class. For example you can set a default transition for {@link
* android.graphics.drawable.Drawable} and that default transition will be used if you
* subsequently start requests for specific {@link android.graphics.drawable.Drawable} types like
* {@link com.bumptech.glide.load.resource.gif.GifDrawable} or {@link
* android.graphics.drawable.BitmapDrawable}. Specific types are always preferred so if you
* register a default transition for both {@link android.graphics.drawable.Drawable} and {@link
* android.graphics.drawable.BitmapDrawable} and then start a request for {@link
* android.graphics.drawable.BitmapDrawable}s, the transition you registered for {@link
* android.graphics.drawable.BitmapDrawable}s will be used.
*/
设置默认TransitionOptions,以便在启动一个将使用给定Class加载资源的请求时使用。
只要这里应用的资源类可以从请求的资源类中分配,那么请求的资源类最好匹配这里应用的资源类,但这并不是必需的。例如,你可以为Drawable设置一个默认的转换,如果你随后开始请求特定的Drawable类型,如GifDrawable或BitmapDrawable,那么这个默认的转换将被使用。特定类型总是首选的,所以如果你注册一个默认的过渡,既可绘制和BitmapDrawable,然后启动一个BitmapDrawables的请求,你注册的BitmapDrawables的过渡将被使用。
注释解释起来挺费劲的。但是它的作用UI设计很喜欢:它是进行效果转换的。比如:圆角、透明度、高斯模糊也就是毛玻璃、圆头像等等图片裁剪处理的变换。
// Public API.
@SuppressWarnings("unused")
@NonNull
public <T> GlideBuilder setDefaultTransitionOptions(
。。。
/**
* Sets the {@link MemorySizeCalculator} to use to calculate maximum sizes for default {@link
* MemoryCache MemoryCaches} and/or default {@link BitmapPool BitmapPools}.
*
* @see #setMemorySizeCalculator(MemorySizeCalculator)
* @param builder The builder to use (will not be modified).
* @return This builder.
*/
设置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());
}
/**
* Sets the {@link MemorySizeCalculator} to use to calculate maximum sizes for default {@link
* MemoryCache MemoryCaches} and/or default {@link BitmapPool BitmapPools}.
*
* <p>The given {@link MemorySizeCalculator} will not affect custom pools or caches provided via
* {@link #setBitmapPool(BitmapPool)} or {@link #setMemoryCache(MemoryCache)}.
*
* @param calculator The calculator to use.
* @return This builder.
*/
设置MemorySizeCalculator用于计算默认的MemoryCache和/或默认的BitmapPool BitmapPools的最大大小。
给定的MemorySizeCalculator不会影响自定义池或通过提供的缓存
setBitmapPool (BitmapPool)或setMemoryCache (MemoryCache)。
// Public API.
@SuppressWarnings("WeakerAccess")
@NonNull
public GlideBuilder setMemorySizeCalculator(@Nullable MemorySizeCalculator calculator) {
。。。
/**
* Sets the {@link com.bumptech.glide.manager.ConnectivityMonitorFactory} to use to notify {@link
* com.bumptech.glide.RequestManager} of connectivity events. If not set {@link
* com.bumptech.glide.manager.DefaultConnectivityMonitorFactory} would be used.
*
* @param factory The factory to use
* @return This builder.
*/
设置ConnectivityMonitorFactory来通知RequestManager连接事件。如果没有设置,将使用DefaultConnectivityMonitorFactory。
ConnectivityMonitorFactory:网络连接监视器工厂,又是一个【工厂模式】应用
// Public API.
@SuppressWarnings("unused")
@NonNull
public GlideBuilder setConnectivityMonitorFactory(@Nullable ConnectivityMonitorFactory factory) {
。。。
/**
* Sets a log level constant from those in {@link Log} to indicate the desired log verbosity.
*
* <p>The level must be one of {@link Log#VERBOSE}, {@link Log#DEBUG}, {@link Log#INFO}, {@link
* Log#WARN}, or {@link Log#ERROR}.
*
* <p>{@link Log#VERBOSE} means one or more lines will be logged per request, including timing
* logs and failures. {@link Log#DEBUG} means at most one line will be logged per successful
* request, including timing logs, although many lines may be logged for failures including
* multiple complete stack traces. {@link Log#INFO} means failed loads will be logged including
* multiple complete stack traces, but successful loads will not be logged at all. {@link
* Log#WARN} means only summaries of failed loads will be logged. {@link Log#ERROR} means only
* exceptional cases will be logged.
*
* <p>All logs will be logged using the 'Glide' tag.
*
* <p>Many other debugging logs are available in individual classes. The log level supplied here
* only controls a small set of informative and well formatted logs. Users wishing to debug
* certain aspects of the library can look for individual <code>TAG</code> variables at the tops
* of classes and use <code>adb shell setprop log.tag.TAG</code> to enable or disable any relevant
* tags.
*
* @param logLevel The log level to use from {@link Log}.
* @return This builder.
*/
从“日志”中设置一个日志级别常量,以指示所需的日志详细程度。
该级别必须是“VERBOSE”、“DEBUG”、“INFO”、“WARN”或“ERROR”中的一个。
Log#VERBOSE意味着每个请求将记录一行或多行,包括计时日志和失败。Log#DEBUG意味着每个成功的请求最多只会记录一行日志,包括计时日志,尽管可能会记录很多行失败的日志,包括多个完整的堆栈跟踪。Log#INFO意味着失败的加载将被记录,包括多个完整的堆栈跟踪,但是成功的加载将完全不被记录。Log#WARN表示只记录失败加载的摘要。日志#ERROR表示只会记录异常情况。所有日志将使用'Glide'标签记录。许多其他调试日志可以在单独的类中使用。这里提供的日志级别仅控制少量信息丰富且格式良好的日志。希望调试库的某些方面的用户可以在类的顶部查找单个的<code>TAG</code>变量,并使用<code>adb shell setprop log.tag。TAG</code>启用或禁用任何相关标签。
// Public API.
@SuppressWarnings("unused")
@NonNull
public GlideBuilder setLogLevel(int logLevel) {
。。。
/**
* If set to {@code true}, allows Glide to re-capture resources that are loaded into {@link
* com.bumptech.glide.request.target.Target}s which are subsequently de-referenced and garbage
* collected without being cleared.
*
* <p>Defaults to {@code false}.
*
* <p>Glide's resource re-use system is permissive, which means that's acceptable for callers to
* load resources into {@link com.bumptech.glide.request.target.Target}s and then never clear the
* {@link com.bumptech.glide.request.target.Target}. To do so, Glide uses {@link
* java.lang.ref.WeakReference}s to track resources that belong to {@link
* com.bumptech.glide.request.target.Target}s that haven't yet been cleared. Setting this method
* to {@code true} allows Glide to also maintain a hard reference to the underlying resource so
* that if the {@link com.bumptech.glide.request.target.Target} is garbage collected, Glide can
* return the underlying resource to it's memory cache so that subsequent requests will not
* unexpectedly re-load the resource from disk or source. As a side affect, it will take the
* system slightly longer to garbage collect the underlying resource because the weak reference
* has to be cleared and processed before the hard reference is removed. As a result, setting this
* method to {@code true} may transiently increase the memory usage of an application.
*
* <p>Leaving this method at the default {@code false} value will allow the platform to garbage
* collect resources more quickly, but will lead to unexpected memory cache misses if callers load
* resources into {@link com.bumptech.glide.request.target.Target}s but never clear them.
*
* <p>If you set this method to {@code true} you <em>must not</em> call {@link Bitmap#recycle()}
* or mutate any Bitmaps returned by Glide. If this method is set to {@code false}, recycling or
* mutating Bitmaps is inefficient but safe as long as you do not clear the corresponding {@link
* com.bumptech.glide.request.target.Target} used to load the {@link Bitmap}. However, if you set
* this method to {@code true} and recycle or mutate any returned {@link Bitmap}s or other mutable
* resources, Glide may recover those resources and attempt to use them later on, resulting in
* crashes, graphical corruption or undefined behavior.
*
* <p>Regardless of what value this method is set to, it's always good practice to clear {@link
* com.bumptech.glide.request.target.Target}s when you're done with the corresponding resource.
* Clearing {@link com.bumptech.glide.request.target.Target}s allows Glide to maximize resource
* re-use, minimize memory overhead and minimize unexpected behavior resulting from edge cases. If
* you use {@link RequestManager#clear(Target)}, calling {@link Bitmap#recycle()} or mutating
* {@link Bitmap}s is not only unsafe, it's also totally unnecessary and should be avoided. In all
* cases, prefer {@link RequestManager#clear(Target)} to {@link Bitmap#recycle()}.
*
* @return This builder.
*/
如果设置为true,允许Glide重新捕获加载到目标中的资源,这些资源随后被解除引用并被垃圾收集,而不被清除。默认值为false。Glide的资源重用系统是允许的,这意味着调用者可以将资源加载到Target中,然后从不清除Target。为此,Glide使用WeakReferences来跟踪属于target的尚未清除的资源。将此方法设置为true允许Glide也维护对底层资源的硬引用,以便如果Target被垃圾收集,Glide可以将底层资源返回到它的内存缓存中,以便后续请求不会意外地从磁盘或源重新加载资源。作为一个副作用,系统将花费更长的时间来垃圾收集底层资源,因为在硬引用被删除之前必须清除和处理弱引用。因此,将此方法设置为true可能会暂时增加应用程序的内存使用量。将此方法保留为默认false值将允许平台更快地垃圾收集资源,但如果调用者将资源加载到target中,将导致意外的内存缓存丢失。目标,但从未清除。如果你设置这个方法为真,你<em>一定不能</em>调用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(
。。。
/**
* Adds a global {@link RequestListener} that will be added to every request started with Glide.
*
* <p>Multiple {@link RequestListener}s can be added here, in {@link RequestManager} scopes or to
* individual {@link RequestBuilder}s. {@link RequestListener}s are called in the order they're
* added. Even if an earlier {@link RequestListener} returns {@code true} from {@link
* RequestListener#onLoadFailed(GlideException, Object, Target, boolean)} or {@link
* RequestListener#onResourceReady(Object, Object, Target, DataSource, boolean)}, it will not
* prevent subsequent {@link RequestListener}s from being called.
*
* <p>Because Glide requests can be started for any number of individual resource types, any
* listener added here has to accept any generic resource type in {@link
* RequestListener#onResourceReady(Object, Object, Target, DataSource, boolean)}. If you must base
* the behavior of the listener on the resource type, you will need to use {@code instanceof} to
* do so. It's not safe to cast resource types without first checking with {@code instanceof}.
*/
添加一个全局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<Object> listener) {
。。。
/**
* Set to {@code true} to make Glide populate {@link
* com.bumptech.glide.load.engine.GlideException#setOrigin(Exception)} for failed requests.
*
* <p>The exception set by this method is not printed by {@link GlideException} and can only be
* viewed via a {@link RequestListener} that reads the field via {@link
* GlideException#getOrigin()}.
*
* <p>This is an experimental API that may be removed in the future.
*/
设置为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
/** *A resource interface that wraps a particular type so that it
can be pooled and reused.
@param The type of resource wrapped by this class. */
一种资源接口,它包装了特定的类型,以便它可以被合用和复用。
参数:可包装的资源类
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
/** * Provides type independent options to customize loads with
Glide. * *Non-final to allow Glide’s generated classes to be
assignable to their non-generated * equivalents. */
@SuppressWarnings(“PMD.UseUtilityClass”)
Glide 提供类型独立可选项,用于自定义加载策略
Non-final允许Glide生成的类可以赋值给它们的非生成类。
com.bumptech.glide.request.BaseRequestOptions
/**
* A base object to allow method sharing between {@link RequestOptions} and {@link
* com.bumptech.glide.RequestBuilder}.
*
* <p>This class is not meant for general use and may change at any time.
*
* @param <T> The particular child implementation
*/
一个允许RequestOptions和RequestBuilder之间方法共享的基础对象。
个类不是一般使用的,可能随时更改
特定的子实现
com.bumptech.glide.Glide.RequestOptionsFactory
/** Creates a new instance of {@link RequestOptions}. */
创建一个新的RequestOptions实例
com.bumptech.glide.RequestBuilder
/**
* A generic class that can handle setting options and staring loads for generic resource types.
*
@param <TranscodeType> The type of resource that will be delivered to the {@link
* com.bumptech.glide.request.target.Target}.
*/
一个泛型类,可以处理泛型资源类型的设置选项和启动加载
参数 将被交付给目标的资源类型
com.bumptech.glide.load.engine.cache.MemorySizeCalculator
/**
* A calculator that tries to intelligently determine cache sizes for a given device based on some
* constants and the devices screen density, width, and height.
*/
一个计算器,试图智能决定缓存大小为给定的设备基于一些常量和设备屏幕密度,宽度和高度。
com.bumptech.glide.manager.ConnectivityMonitorFactory
/**
* A factory class that produces a functional {@link
* com.bumptech.glide.manager.ConnectivityMonitor}.
*/
一个工厂类,产生一个功能性的ConnectivityMonitor。
com.bumptech.glide.RequestManager
/**
* A class for managing and starting requests for Glide. Can use activity, fragment and connectivity
* lifecycle events to intelligently stop, start, and restart requests. Retrieve either by
* instantiating a new object, or to take advantage built in Activity and Fragment lifecycle
* handling, use the static Glide.load methods with your Fragment or Activity.
*
* @see Glide#with(android.app.Activity)
* @see Glide#with(androidx.fragment.app.FragmentActivity)
* @see Glide#with(android.app.Fragment)
* @see Glide#with(androidx.fragment.app.Fragment)
* @see Glide#with(Context)
*/
一个管理和启动Glide请求的课程。可以使用活动、片段和连接生命周期事件来智能地停止、启动和重新启动请求。通过实例化一个新对象来获取,或者利用内置的Activity和Fragment生命周期处理,使用静态的Glide。加载方法与你的Fragment或Activity。
com.bumptech.glide.manager.DefaultConnectivityMonitorFactory
/**
* A factory class that produces a functional {@link com.bumptech.glide.manager.ConnectivityMonitor}
* if the application has the {@code android.permission.ACCESS_NETWORK_STATE} permission and a no-op
* non functional {@link com.bumptech.glide.manager.ConnectivityMonitor} if the app does not have
* the required permission.
*/
一个工厂类,如果应用程序有ACCESS_NETWORK_STATE权限,它会生成一个功能性的ConnectivityMonitor;如果应用程序没有必要的权限,它会生成一个无操作的非功能性的ConnectivityMonitor。
com.bumptech.glide.manager.ConnectivityMonitor
An interface for monitoring network connectivity events.
监视网络连接事件的接口。
com.bumptech.glide.request.target.Target
/**
* An interface that Glide can load a resource into and notify of relevant lifecycle events during a
* load.
*
* <p>The lifecycle events in this class are as follows:
*
* <ul>
* <li>onLoadStarted
* <li>onResourceReady
* <li>onLoadCleared
* <li>onLoadFailed
* </ul>
*
* The typical lifecycle is onLoadStarted -> onResourceReady or onLoadFailed -> onLoadCleared.
* However, there are no guarantees. onLoadStarted may not be called if the resource is in memory or
* if the load will fail because of a null model object. onLoadCleared similarly may never be called
* if the target is never cleared. See the docs for the individual methods for details.
*
* @param <R> The type of resource the target can display.
*/
一个接口,Glide可以将资源加载到该接口中,并在加载期间通知相关的生命周期事件。
这个类中的生命周期事件如下:
onLoadStarted
onResourceReady
onLoadCleared
onLoadFailed
典型的生命周期是onLoadStarted -> onResourceReady或onLoadFailed -> onLoadCleared。
然而,这并不能保证。如果资源在内存中,或者由于一个空模型对象而导致加载失败,onLoadStarted可能不会被调用。同样,如果目标从未被清除,onLoadCleared也可能永远不会被调用。有关具体方法的详细信息,请参阅文档。
*
- @param 目标可以显示的资源类型。
com.bumptech.glide.request.RequestListener
/**
* A class for monitoring the status of a request while images load.
*
* <p>All methods in this interface will be called from a background thread if the {@code
* RequestListener} is added to a request that is started with {@link RequestBuilder#submit()},
* {@link RequestBuilder#submit(int, int)}, or {@link RequestBuilder#into(int, int)}. Those methods
* no longer post results back to the main thread to avoid the unnecessary thread interactions and
* corresponding latency. As a side affect though, listeners added to those requests are no longer
* called on the main thread. {@code RequestListeners} added to requests started with {@link
* RequestBuilder#into(Target)} or {@link RequestBuilder#into(ImageView)} will continue to be called
* back on the main thread.
*
* @param <R> The type of resource being loaded.
*/
一个类,用于在图像加载时监视请求的状态。
如果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
/** An exception with zero or more causes indicating why a load in Glide failed. */
一个异常,零或多个原因表明为什么在Glide加载失败
更多设计模式解读
单例模式
Glide设计模式之单例模式
空对象模式
Glide设计模式之空对象模式【EmptyModelLoader】【EmptyList<E>
建造者模式
Glide多种组合使用方式记录–没有全部亲测,大家可以根据实际需要选用
Glide设计模式之建造者(builder)模式1【GlideBuilder】
Glide设计模式之建造者(builder)模式2【RequestBuilder】
Glide设计模式之建造者(builder)模式3【RequestOptions】【BaseRequestOptions】
Glide设计模式之建造者(builder)模式4总结【MemorySizeCalculator】【GlideExecutor】【PreFillType】【LazyHeaders】
工厂模式
Glide设计模式之工厂模式1【ModelLoaderFactory】
Glide设计模式之工厂模式2【DiskCache.Factory】
Glide工厂模式3【TransitionFactory】【Transition】
Glide设计模式之工厂模式4总结
自研产品推荐
历时一年半多开发终于smartApi-v1.0.0版本在2023-09-15晚十点正式上线
smartApi是一款对标国外的postman的api调试开发工具,由于开发人力就作者一个所以人力有限,因此v1.0.0版本功能进行精简,大功能项有:
- api参数填写
- api请求响应数据展示
- PDF形式的分享文档
- Mock本地化解决方案
- api列表数据本地化处理
- 再加上UI方面的打磨
为了更好服务大家把之前的公众号和软件激活结合,如有疑问请大家反馈到公众号即可,下个版本30%以上的更新会来自公众号的反馈。
嗯!先解释不上服务端原因,API调试工具的绝大多数时候就是一个数据模型、数据处理、数据模型理解共识的问题解决工具,所以作者结合自己十多年开发使用的一些痛点来打造的,再加上服务端开发一般是面向企业的,作者目前没有精力和时间去打造企业服务。再加上没有资金投入所以服务端开发会滞后,至于什么时候会进行开发,这个要看募资情况和用户反馈综合考虑。虽然目前国内有些比较知名的api工具了,但作者使用后还是觉得和实际使用场景不符。如果有相关吐槽也可以在作者的公众号里反馈蛤!
下面是一段smartApi使用介绍: