Glide源码阅读之工厂模式1【ModelLoaderFactory】【ModelLoader】
参考阅读:
Glide多种组合使用方式记录–没有全部亲测,大家可以根据实际需要选用
Glide设计模式之工厂模式1【ModelLoaderFactory】
Glide设计模式之工厂模式2【DiskCache.Factory】
Glide工厂模式3【TransitionFactory】【Transition】
Glide设计模式之工厂模式4总结
使用场景介绍
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决:主要解决接口选择的问题。
何时使用:我们明确地计划不同条件下创建不同实例时。
如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。
关键代码:创建过程在其子类执行。
优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口
缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
使用场景: 1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。 2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。 3、设计一个连接服务器的框架,需要三个协议,“POP3”、“IMAP”、“HTTP”,可以把这三个作为产品类,共同实现一个接口。
注意事项:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
主要解决:主要解决接口选择的问题。
何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
如何解决:在一个产品族里面,定义多个产品。
关键代码:在一个工厂里聚合多个同类产品。
应用实例:工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。假设一种情况(现实中是不存在的,要不然,没法进入共产主义了,但有利于说明抽象工厂模式),在您的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OOP 的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
使用场景: 1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。
注意事项:产品族难扩展,产品等级易扩展。
建议:阅读完Glide里面几个工厂模式后发现都比较晦涩,抽象程度比较高。如果对基础设计模式了解比较少,先看看菜鸟教程|设计模式,
如果读完上面的工厂模式和抽象工厂模式后发现疑惑比较多。个人建议下面的Glide工厂模式源码解析就不要向下看了。如果本身就比较了解工厂模式那也建议慢点阅读。下面的源码解析作者本人能力有限不一定说的很明白,如有理解上冲突请留言讨论。如有错漏请留言斧正。
====================================================
ModelLoaderFactory
com.bumptech.glide.load.model.ModelLoaderFactory
/**
* An interface for creating a {@link ModelLoader} for a given model type.
*
* <p>The application {@link android.content.Context} can be passed in to the constructor of the
* factory when necessary. It's unsafe to retain {@link android.app.Activity} {@link
* android.content.Context}s in factories. The {@link android.content.Context} can be obtained from
* {@link com.bumptech.glide.module.LibraryGlideModule#registerComponents(Context, Glide, Registry)}
* in most cases.
*
* @param <T> The type of the model the {@link com.bumptech.glide.load.model.ModelLoader}s built by
* this factory can handle
* @param <Y> The type of data the {@link com.bumptech.glide.load.model.ModelLoader}s built by this
* factory can load.
*/
为给定模型类型创建ModelLoader的接口。
应用程序上下文可以在必要时传递给工厂的构造函数。在工厂中保留Activity中Context是不安全的。在大多数情况下Context可以从LibraryGlideModule.registerComponents(Context, Glide, Registry)中获取。。
类型参数:
T -由该工厂构建的ModelLoaders可以处理的模型类型
Y -由该工厂构建的ModelLoaders可以加载的数据类型。
public interface ModelLoaderFactory<T, Y> {
/**
* Build a concrete ModelLoader for this model type.
*
* @param multiFactory A map of classes to factories that can be used to construct additional
* {@link ModelLoader}s that this factory's {@link ModelLoader} may depend on
* @return A new {@link ModelLoader}
*/
为这个模型类型构建一个具体的ModelLoader。
参数:
multiFactory -类到工厂的映射,可以用来构造额外的ModelLoader,该工厂的ModelLoader可能依赖于这些ModelLoader
返回:
一个新的ModelLoader
@NonNull
ModelLoader<T, Y> build(@NonNull MultiModelLoaderFactory multiFactory);
/** A lifecycle method that will be called when this factory is about to replaced. */
当这个工厂即将被替换时将被调用的生命周期方法。
void teardown();
}
ModelLoaderFactory意图
主要是生产出ModelLoader<Model, Data>,至于生产出来后怎么使用,这个后面再解析说明。Glide源码结构对这一块和使用Glide.with(myFragment).load(url).into(myImageView)联系在比较深的代码结构里,表面上不是很容易一眼就看明白。基于目前的工厂模式生产过程判断不准具体是哪个环节进行生产后使用ModelLoader对象。
包路径:com.bumptech.glide.load.model.ModelLoader
/**
* A factory interface for translating an arbitrarily complex data model into a concrete data type
* that can be used by an {@link DataFetcher} to obtain the data for a resource represented by the
* model.
*
* <p>This interface has two objectives: 1. To translate a specific model into a data type that can
* be decoded into a resource.
*
* <p>2. To allow a model to be combined with the dimensions of the view to fetch a resource of a
* specific size.
*
* <p>This not only avoids having to duplicate dimensions in xml and in your code in order to
* determine the size of a view on devices with different densities, but also allows you to use
* layout weights or otherwise programmatically put the dimensions of the view without forcing you
* to fetch a generic resource size.
*
* <p>The smaller the resource you fetch, the less bandwidth and battery life you use, and the lower
* your memory footprint per resource.
*
* @param <Model> The type of the model.
* @param <Data> The type of the data that can be used by a {@link
* com.bumptech.glide.load.ResourceDecoder} to decode a resource.
*/
一种工厂接口,用于将任意复杂的数据模型转换为具体的数据类型,DataFetcher可以使用该数据类型为模型所表示的资源获取数据。
这个接口有两个目标:
1。将特定模型转换为可以解码为资源的数据类型。
2. 允许模型与视图的维度组合,以获取特定大小的资源。
这不仅避免了重复的维度在xml和代码中为了确定大小的设备上有不同的密度,而且还允许您使用布局权重或通过编程将视图的尺寸没有强迫你去拿一个通用的资源大小。
获取的资源越小,占用的带宽和电池寿命就越短,每个资源占用的内存就越少。
类型参数:
模型-模型的类型。
Data - ResourceDecoder可用于解码资源的数据类型。
public interface ModelLoader<Model, Data> {
/**
* Contains a set of {@link com.bumptech.glide.load.Key Keys} identifying the source of the load,
* alternate cache keys pointing to equivalent data, and a {@link
* com.bumptech.glide.load.data.DataFetcher} that can be used to fetch data not found in cache.
*
* @param <Data> The type of data that well be loaded.
*/
包含一组标识加载源的键、指向等效数据的备用缓存键和一个DataFetcher,该键可用于获取不在缓存中找到的数据。
类型参数:
数据-要加载的数据类型。
class LoadData<Data> {
public final Key sourceKey;
public final List<Key> alternateKeys;
public final DataFetcher<Data> fetcher;
public LoadData(@NonNull Key sourceKey, @NonNull DataFetcher<Data> fetcher) {
this(sourceKey, Collections.<Key>emptyList(), fetcher);
}
public LoadData(
@NonNull Key sourceKey,
@NonNull List<Key> alternateKeys,
@NonNull DataFetcher<Data> fetcher) {
this.sourceKey = Preconditions.checkNotNull(sourceKey);
this.alternateKeys = Preconditions.checkNotNull(alternateKeys);
this.fetcher = Preconditions.checkNotNull(fetcher);
}
}
/**
* Returns a {@link com.bumptech.glide.load.model.ModelLoader.LoadData} containing a {@link
* com.bumptech.glide.load.data.DataFetcher} required to decode the resource represented by this
* model, as well as a set of {@link com.bumptech.glide.load.Key Keys} that identify the data
* loaded by the {@link com.bumptech.glide.load.data.DataFetcher} as well as an optional list of
* alternate keys from which equivalent data can be loaded. The {@link DataFetcher} will not be
* used if the resource is already cached.
*
* <p>Note - If no valid data fetcher can be returned (for example if a model has a null URL),
* then it is acceptable to return a null data fetcher from this method.
*
* @param model The model representing the resource.
* @param width The width in pixels of the view or target the resource will be loaded into, or
* {@link com.bumptech.glide.request.target.Target#SIZE_ORIGINAL} to indicate that the
* resource should be loaded at its original width.
* @param height The height in pixels of the view or target the resource will be loaded into, or
* {@link com.bumptech.glide.request.target.Target#SIZE_ORIGINAL} to indicate that the
* resource should be loaded at its original height.
*/
返回一个ModelLoader。LoadData包含解码该模型所表示的资源所需的DataFetcher,以及一组标识由DataFetcher加载的数据的键,以及一个可选的备用键列表,从中可以加载等价的数据。如果资源已经缓存,则不会使用DataFetcher。
注意:如果没有有效的数据获取器可以返回(例如,如果一个模型有一个空URL),那么从这个方法返回一个空数据获取器是可以接受的。
参数:
model—表示资源的模型。
width -资源将被加载到的视图或目标的宽度,以像素为单位。SIZE_ORIGINAL表示资源应该按原始宽度加载。
height -资源将被加载到的视图或目标的高度,以像素为单位。SIZE_ORIGINAL表示资源应该在其初始高度加载。
@Nullable
LoadData<Data> buildLoadData(
@NonNull Model model, int width, int height, @NonNull Options options);
/**
* Returns true if the given model is a of a recognized type that this loader can probably load.
*
* <p>For example, you may want multiple Uri -> InputStream loaders. One might handle media store
* Uris, another might handle asset Uris, and a third might handle file Uris etc.
*
* <p>This method is generally expected to do no I/O and complete quickly, so best effort results
* are acceptable. {@link ModelLoader ModelLoaders} that return true from this method may return
* {@code null} from {@link #buildLoadData(Object, int, int, Options)}
*/
如果给定的模型是此加载器可能加载的可识别类型,则返回true。
例如,您可能需要多个Uri -> InputStream加载器。一个可能处理媒体存储uri,另一个可能处理资产uri,第三个可能处理文件uri等。
这种方法通常不需要执行I/O,并且可以快速完成,因此可以获得最佳的效果。从这个方法返回true的ModelLoaders可能会从buildLoadData(Object, int, int, Options)返回null
boolean handles(@NonNull Model model);
}
ModelLoaderFactory已知实现类列表:
- AssetUriLoader.FileDescriptorFactory
- AssetUriLoader.StreamFactory
- ByteArrayLoader.ByteBufferFactory
- ByteArrayLoader.StreamFactory
- ByteBufferFileLoader.Factory
- DataUrlLoader.StreamFactory
- FileLoader.Factory
- FileLoader.FileDescriptorFactory
- FileLoader.StreamFactory
- HttpGlideUrlLoader.Factory
- HttpUriLoader.Factory
- MediaStoreFileLoader.Factory
- MediaStoreImageThumbLoader.Factory
- MediaStoreVideoThumbLoader.Factory
- OkHttpUrlLoader.Factory
- OkHttpUrlLoader.Factory
- QMediaStoreUriLoader.FileDescriptorFactory
- QMediaStoreUriLoader.InputStreamFactory
- ResourceLoader.AssetFileDescriptorFactory
- ResourceLoader.FileDescriptorFactory
- ResourceLoader.StreamFactory
- ResourceLoader.UriFactory
- StringLoader.AssetFileDescriptorFactory
- StringLoader.FileDescriptorFactory
- StringLoader.StreamFactory
- UnitModelLoader.Factory
- UriLoader.AssetFileDescriptorFactory
- UriLoader.FileDescriptorFactory
- UriLoader.StreamFactory
- UrlLoader.StreamFactory
- UrlUriLoader.StreamFactory
- VolleyUrlLoader.Factory
AssetUriLoader.FileDescriptorFactory
com.bumptech.glide.load.model.AssetUriLoader.FileDescriptorFactory
/** Factory for loading {@link ParcelFileDescriptor}s from asset manager Uris. */
从asset manager uri中加载ParcelFileDescriptors的工厂。
public static class FileDescriptorFactory
implements ModelLoaderFactory<Uri, ParcelFileDescriptor>,
AssetFetcherFactory<ParcelFileDescriptor> {
private final AssetManager assetManager;
public FileDescriptorFactory(AssetManager assetManager) {
this.assetManager = assetManager;
}
@NonNull
@Override
public ModelLoader<Uri, ParcelFileDescriptor> build(MultiModelLoaderFactory multiFactory) {
return new AssetUriLoader<>(assetManager, this);
}
@Override
public void teardown() {
// Do nothing.
}
@Override
public DataFetcher<ParcelFileDescriptor> buildFetcher(
AssetManager assetManager, String assetPath) {
return new FileDescriptorAssetPathFetcher(assetManager, assetPath);
}
}
AssetUriLoader.StreamFactory
com.bumptech.glide.load.model.AssetUriLoader.StreamFactory
/** Factory for loading {@link InputStream}s from asset manager Uris. */
public static class StreamFactory
implements ModelLoaderFactory<Uri, InputStream>, AssetFetcherFactory<InputStream> {
private final AssetManager assetManager;
public StreamFactory(AssetManager assetManager) {
this.assetManager = assetManager;
}
@NonNull
@Override
public ModelLoader<Uri, InputStream> build(MultiModelLoaderFactory multiFactory) {
return new AssetUriLoader<>(assetManager, this);
}
@Override
public void teardown() {
// Do nothing.
}
@Override
public DataFetcher<InputStream> buildFetcher(AssetManager assetManager, String assetPath) {
return new StreamAssetPathFetcher(assetManager, assetPath);
}
}
AssetUriLoader.AssetFetcherFactory(组合使用的另一个抽象工厂接口)
com.bumptech.glide.load.model.AssetUriLoader.AssetFetcherFactory
/**
* A factory to build a {@link DataFetcher} for a specific asset path.
* * @param <Data> The type of data that will be obtained by the fetcher.
*/
为特定 asset 路径构建DataFetcher的工厂
类型参数:
数据-将由提取器获得的数据类型。
public interface AssetFetcherFactory<Data> {
DataFetcher<Data> buildFetcher(AssetManager assetManager, String assetPath);
}
实现类列表如下:
- AssetUriLoader.FileDescriptorFactory
- AssetUriLoader.StreamFactory
小计:ModelLoaderFactory、AssetFetcherFactory
在AssetUriLoader中的内部工厂类FileDescriptorFactory、StreamFactory实现了ModelLoaderFactory和AssetFetcherFactory的接口。这样的组合基本符合抽象工厂模式的使用方式。设计模式的实际使用都是结合实际的生产业务环境和编码人员的喜好的。所以对基本的设计模式越熟悉,就能越熟练地看出编码人员的设计意图和使用的是哪个设计模式变化的。下面接着介绍其他的ModelLoaderFactory接口实现类,看看还有哪些变化,为了便于熟悉使用结构,具体的实现过程就略过了。如果感兴趣的可以根据类的具体包名查看类方法的具体实现。
如有疑问请留言!
如果觉得工厂模式已经很熟悉了。那下面的可以略过不用阅读了。下面部分旨在解析ModelLoaderFactory具体使用结构。多熟悉熟悉它的各种工厂模式的实现。这样才能培养自己写工厂模式的感觉和为以后高效阅读Android源码作准备(作者又给自己挖坑了,就是这样的解析方式不知道读者能否接受,作者也看过不少讲解Android源码的书籍,虽然讲的的确很好,但是在实际项目开发中发现用到很少,过了一段时间就都忘了。所以本着拿来即用的主义去解析很火的开源项目和系统源码。总结出能拿来即用的设计实践,不负自己的心血,不负读者的关注)
ByteArrayLoader.ByteBufferFactory和ByteArrayLoader.StreamFactory
com.bumptech.glide.load.model.ByteArrayLoader.ByteBufferFactory
/**
* Factory for {@link com.bumptech.glide.load.model.ByteArrayLoader} and {@link
* java.nio.ByteBuffer}.
*/
ByteArrayLoader和ByteBuffer的工厂
public static class ByteBufferFactory implements ModelLoaderFactory<byte[], ByteBuffer> {
。。。
/** Factory for {@link ByteArrayLoader} and {@link java.io.InputStream}. */
ByteArrayLoader和InputStream的工厂。
public static class StreamFactory implements ModelLoaderFactory<byte[], InputStream> {
。。。
ByteBufferFileLoader.Factory
包路径:com.bumptech.glide.load.model.ByteBufferFileLoader.Factory
/** Factory for {@link com.bumptech.glide.load.model.ByteBufferFileLoader}. */
ByteBufferFileLoader工厂。
public static class Factory implements ModelLoaderFactory<File, ByteBuffer> {
。。。
DataUrlLoader.StreamFactory
包路径:com.bumptech.glide.load.model.DataUrlLoader.StreamFactory
/**
* Factory for loading {@link InputStream}s from data uris.
*
* @param <Model> The type of Model we can obtain data for, e.g. String.
*/
从数据uri中加载InputStreams的工厂。
public static final class StreamFactory<Model> implements ModelLoaderFactory<Model, InputStream> {
FileLoader.Factory
包路径:com.bumptech.glide.load.model.FileLoader.Factory
/**
* Base factory for loading data from {@link java.io.File files}.
*
* @param <Data> The type of data that will be loaded for a given {@link java.io.File}.
*/
从文件中加载数据的基础工厂。
类型参数:
数据-将为给定的文件加载的数据类型。
public static class Factory<Data> implements ModelLoaderFactory<File, Data> {
FileLoader.FileDescriptorFactory
包路径:com.bumptech.glide.load.model.FileLoader.FileDescriptorFactory
/** Factory for loading {@link ParcelFileDescriptor}s from {@link File}s. */
从Files中加载ParcelFileDescriptors的工厂。
public static class FileDescriptorFactory extends Factory<ParcelFileDescriptor> {
FileLoader.StreamFactory
包路径:com.bumptech.glide.load.model.FileLoader.StreamFactory
/** Factory for loading {@link InputStream}s from {@link File}s. */
从文件中加载InputStreams的工厂。
public static class StreamFactory extends Factory<InputStream> {
。。。
HttpGlideUrlLoader.Factory
包路径:com.bumptech.glide.load.model.stream.HttpGlideUrlLoader.Factory
/** The default factory for {@link HttpGlideUrlLoader}s. */
HttpGlideUrlLoaders的默认工厂。
public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
。。。
HttpUriLoader.Factory
包路径:com.bumptech.glide.load.model.stream.HttpUriLoader.Factory
/**
* Factory for loading {@link InputStream}s from http/https {@link Uri}s.
*
* @deprecated Use {@link UrlUriLoader.StreamFactory} instead
*/
从http/https uri加载InputStreams的工厂。
@Deprecated
public static class Factory extends StreamFactory {
。。。
MediaStoreFileLoader.Factory
包路径:com.bumptech.glide.load.model.MediaStoreFileLoader.Factory
/** {@link ModelLoaderFactory} for {@link MediaStoreFileLoader}s. */
public static final class Factory implements ModelLoaderFactory<Uri, File> {
MediaStoreImageThumbLoader.Factory
包路径:com.bumptech.glide.load.model.stream.MediaStoreImageThumbLoader.Factory
/** Factory that loads {@link InputStream}s from media store image {@link Uri}s. */
从媒体存储 image uri中加载InputStreams的工厂
public static class Factory implements ModelLoaderFactory<Uri, InputStream> {
。。。
MediaStoreVideoThumbLoader.Factory
包路径:com.bumptech.glide.load.model.stream.MediaStoreVideoThumbLoader.Factory
/**
* Loads {@link InputStream}s from media store image {@link Uri}s that point to pre-generated
* thumbnails for those {@link Uri}s in the media store.
*/
从媒体存储图像uri加载InputStreams,该uri指向媒体存储中那些uri的预先生成的缩略图。
public static class Factory implements ModelLoaderFactory<Uri, InputStream> {
。。。
OkHttpUrlLoader.Factory
包路径:com.bumptech.glide.integration.okhttp.OkHttpUrlLoader.Factory
/** The default factory for {@link OkHttpUrlLoader}s. */
OkHttpUrlLoaders的默认工厂。
// Public API.
@SuppressWarnings({"WeakerAccess", "deprecation"})
public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
。。。
okhttp3 中OkHttpUrlLoader.Factory
包路径:com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader.Factory
/** The default factory for {@link OkHttpUrlLoader}s. */
OkHttpUrlLoaders的默认工厂。
// Public API.
@SuppressWarnings("WeakerAccess")
public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
。。。
QMediaStoreUriLoader.FileDescriptorFactory
包路径:com.bumptech.glide.load.model.stream.QMediaStoreUriLoader.FileDescriptorFactory
/** Factory for {@link ParcelFileDescriptor}. */
ParcelFileDescriptor工厂。
@RequiresApi(Build.VERSION_CODES.Q)
public static final class FileDescriptorFactory extends Factory<ParcelFileDescriptor> {
。。。
QMediaStoreUriLoader.InputStreamFactory
包路径:com.bumptech.glide.load.model.stream.QMediaStoreUriLoader.InputStreamFactory
/** Factory for {@link InputStream}. */
@RequiresApi(Build.VERSION_CODES.Q)
public static final class InputStreamFactory extends Factory<InputStream> {
。。。
ResourceLoader.AssetFileDescriptorFactory
包路径:
/** Loads {@link AssetFileDescriptor}s from resource ids. */
从资源id中加载AssetFileDescriptors。
public static final class AssetFileDescriptorFactory
implements ModelLoaderFactory<Integer, AssetFileDescriptor> {
。。。
ResourceLoader.FileDescriptorFactory
包路径:com.bumptech.glide.load.model.ResourceLoader.FileDescriptorFactory
/** Factory for loading {@link ParcelFileDescriptor}s from Android resource ids. */
从Android资源id中加载ParcelFileDescriptors的工厂。
public static class FileDescriptorFactory
implements ModelLoaderFactory<Integer, ParcelFileDescriptor> {
。。。
ResourceLoader.StreamFactory
包路径:com.bumptech.glide.load.model.ResourceLoader.StreamFactory
/** Factory for loading {@link InputStream}s from Android resource ids. */
从Android资源id加载InputStreams的工厂。
public static class StreamFactory implements ModelLoaderFactory<Integer, InputStream> {
。。。
ResourceLoader.UriFactory
包路径:com.bumptech.glide.load.model.ResourceLoader.UriFactory
/** Factory for loading resource {@link Uri}s from Android resource ids. */
从Android资源id加载资源uri的工厂。
public static class UriFactory implements ModelLoaderFactory<Integer, Uri> {
。。。
StringLoader.AssetFileDescriptorFactory
包路径:com.bumptech.glide.load.model.StringLoader.AssetFileDescriptorFactory
/** Loads {@link AssetFileDescriptor}s from Strings. */
从字符串中加载AssetFileDescriptors。
public static final class AssetFileDescriptorFactory
implements ModelLoaderFactory<String, AssetFileDescriptor> {
。。。
StringLoader.FileDescriptorFactory
包路径:com.bumptech.glide.load.model.StringLoader.FileDescriptorFactory
/** Factory for loading {@link ParcelFileDescriptor}s from Strings. */
从字符串中加载ParcelFileDescriptors的工厂。
public static class FileDescriptorFactory
implements ModelLoaderFactory<String, ParcelFileDescriptor> {
。。。
StringLoader.StreamFactory
包路径:com.bumptech.glide.load.model.StringLoader.StreamFactory
/** Factory for loading {@link InputStream}s from Strings. */
从字符串中加载InputStreams的工厂。
public static class StreamFactory implements ModelLoaderFactory<String, InputStream> {
。。。
UnitModelLoader.Factory
包路径:com.bumptech.glide.load.model.UnitModelLoader.Factory
/**
* Factory for producing {@link com.bumptech.glide.load.model.UnitModelLoader}s.
*
* @param <Model> The type of model that will also be returned as decodable data.
*/
生产UnitModelLoaders的工厂。
类型参数:
模型——也将作为可解码数据返回的模型类型。
// PMD.SingleMethodSingleton false positive: https://github.com/pmd/pmd/issues/816
@SuppressWarnings("PMD.SingleMethodSingleton")
public static class Factory<Model> implements ModelLoaderFactory<Model, Model> {
。。。
UriLoader.AssetFileDescriptorFactory
包路径:com.bumptech.glide.load.model.UriLoader.AssetFileDescriptorFactory
/** Loads {@link AssetFileDescriptor}s from {@link Uri}s. */
从uri中加载AssetFileDescriptors。
public static final class AssetFileDescriptorFactory
implements ModelLoaderFactory<Uri, AssetFileDescriptor>,
LocalUriFetcherFactory<AssetFileDescriptor> {
UriLoader.FileDescriptorFactory
包路径:com.bumptech.glide.load.model.UriLoader.FileDescriptorFactory
/** Loads {@link ParcelFileDescriptor}s from {@link Uri}s. */
从uri中加载ParcelFileDescriptors。
public static class FileDescriptorFactory
implements ModelLoaderFactory<Uri, ParcelFileDescriptor>,
LocalUriFetcherFactory<ParcelFileDescriptor> {
。。。
UriLoader.StreamFactory
包路径:com.bumptech.glide.load.model.UriLoader.StreamFactory
/** Loads {@link InputStream}s from {@link Uri}s. */
从uri加载InputStreams。
public static class StreamFactory
implements ModelLoaderFactory<Uri, InputStream>, LocalUriFetcherFactory<InputStream> {
。。。
UrlLoader.StreamFactory
包路径:com.bumptech.glide.load.model.stream.UrlLoader.StreamFactory
/** Factory for loading {@link InputStream}s from {@link URL}s. */
从url加载InputStreams的工厂。
public static class StreamFactory implements ModelLoaderFactory<URL, InputStream> {
。。。
UrlUriLoader.StreamFactory
包路径:com.bumptech.glide.load.model.UrlUriLoader.StreamFactory
/**
* Loads {@link java.io.InputStream InputStreams} from {@link android.net.Uri Uris} with http or
* https schemes.
*/
使用http或https模式从uri加载InputStreams。
public static class StreamFactory implements ModelLoaderFactory<Uri, InputStream> {
。。。
VolleyUrlLoader.Factory
包路径:com.bumptech.glide.integration.volley.VolleyUrlLoader.Factory
/** The default factory for {@link VolleyUrlLoader}s. */
Volley url loaders的默认工厂。
// Public API.
@SuppressWarnings("WeakerAccess")
public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
。。。
总结
从ModelLoader<Model, Data>、ModelLoaderFactory<T, Y>接口业务理解,就是把不同的数据类型的数据Data进行加工成各种可用的Model类型。这里大概有下面几种数据类型数据以及model类型
- <Uri, Data>生产AssetUriLoader、UrlUriLoader、UriLoader;UrlUriLoader生产HttpUriLoader
- <Model, InputStream>生产BaseGlideUrlLoader;BaseGlideUrlLoader生产FlickrModelLoader;BaseGlideUrlLoader<Api.GifResult>生产GiphyModelLoader;BaseGlideUrlLoader生产TestLoader
- <byte[], Data>生产ByteArrayLoader
- <File, ByteBuffer>生产ByteBufferFileLoader
- <GlideUrl, T>生产ChromiumUrlLoader
- <Model, Data>生产DataUrlLoader<Model, Data>
- <Object, Object>生产EmptyModelLoader;这个生产了一个空对象模式
- <T, InputStream>生产FakeModelLoader
- <File, Data>生产FileLoader
- <GlideUrl, InputStream>生产HttpGlideUrlLoader
- <Uri, File>生产MediaStoreFileLoader
- <Uri, InputStream>生产MediaStoreImageThumbLoader、MediaStoreVideoThumbLoader
- <ModelT, DataT>生产MockModelLoader<ModelT, DataT>
- <Model, Data>生产MultiModelLoader<Model, Data>
- <GlideUrl, InputStream>生产OkHttpUrlLoader、VolleyUrlLoader
- <Uri, DataT>生产QMediaStoreUriLoader
- <Integer, Data>生产ResourceLoader
- <String, Data>生产StringLoader
- <Model, Mode>生产UnitModelLoader
- <URL, InputStream>生产UrlLoader
- <GlideUrl, InputStream>生产VolleyUrlLoader
- <WaitModel, Data>生产WaitModelLoader<Model, Data>
以上就是把原材料通过加工厂生产成对应的产品。经过这样的理解干掉中间那些具体的过程就能达成目的的一致性了。写的也像是人说的话了。因为版本的不同可能有些不用了,或者添加了新的ModelLoader<Model, Data>实现类,这里不足再道了。
当然本人也很鼓励读者自定义ModelLoader<Model, Data>类型然后自己实现工厂生产出自定义的产品类。哈哈!就是目前没有给出具体怎么用,这里先保留一下,后面的解析搞具体了再回头补齐这块。这样大家就可以基于Glide框架结构定义自己的各种实现了。等达到这一步那恭喜你可以给Glide贡献代码试试!如果大佬你的代码被纳入Glide那记得留言庆祝。。。
虽然工厂模式的接口和类比较多,但抓住接口和实现接口以及抽象工厂接口这三者之间的关系,也就很容易的理解了这些类在其中扮演的角色了。
再写几句,看到这里估计有读者会想:描述一下ModelLoader<Model, Data>、ModelLoaderFactory<T, Y>接口和一个实现类比如EmptyModelLoader就能说清楚了。干嘛把所有的都列出来哩!!!
刚开始我也是这么想的,可是在把第一个实现类写完后发现自己也很迷惑这个过程干了啥!感觉啥都没有说似的。后来费劲巴力的把这些实现类都给列出来后感觉就清晰了。就是反复实现了工厂结构模式。看的越多感觉就越清楚,对其中的理解也就越清楚了。这些类和接口以后再回头看也不会忘记。就这样一遍又一遍的创建类实现,创建工厂实现,在不同的参数下生产不同的产品类型。慢慢的忽略了其中实现的具体过程。直接从源数据经过两个环节后生产了目标类。这样这一系列的接口和类印象就深刻了。到时候也能脱口而出这些类型的数据转换成类的了。读懂我这篇ModelLoaderFactory、ModelLoader<Model, Data>相关的类再看源码即可跳着看了。就这么回事。把各类数据生产加工成实现的类。
附录1:相关类说明
com.bumptech.glide.load.model.UnitModelLoader
/**
* A put of helper classes that performs no loading and instead always returns the given model as
* the data to decode.
*
* @param <Model> The type of model that will also be returned as decodable data.
*/
助手类的放置,不执行加载,而是总是返回给定的模型作为解码的数据
com.bumptech.glide.load.model.ByteArrayLoader
/**
* A base class to convert byte arrays to input streams so they can be decoded. This class is
* abstract because there is no simple/quick way to generate an id from the bytes themselves, so
* subclass must include an id.
*
* @param <Data> The type of data that will be loaded from a given byte array.
*/
将字节数组转换为输入流以便对其进行解码的基类。这个类是抽象的,因为没有简单/快速的方法来从字节本身生成id,所以子类必须包含一个id。
类型参数:
数据-将从给定字节数组加载的数据类型。
com.bumptech.glide.load.model.ByteBufferFileLoader
/** Loads {@link java.nio.ByteBuffer}s using NIO for {@link java.io.File}. */
public class ByteBufferFileLoader implements ModelLoader<File, ByteBuffer> {
。。。
com.bumptech.glide.module.LibraryGlideModule
/**
* Registers a set of components to use when initializing Glide within an app when Glide's
* annotation processor is used.
*
* <p>Any number of LibraryGlideModules can be contained within any library or application.
*
* <p>LibraryGlideModules are called in no defined order. If LibraryGlideModules within an
* application conflict, {@link AppGlideModule}s can use the {@link
* com.bumptech.glide.annotation.Excludes} annotation to selectively remove one or more of the
* conflicting modules.
*/
@SuppressWarnings("deprecation")
public abstract class LibraryGlideModule implements RegistersComponents {
。。。
当使用Glide的注释处理器时,注册一组在应用程序中初始化Glide时使用的组件。
任何数量的libraryglidemodule都可以包含在任何库或应用程序中。
libraryglidemodule的调用没有定义顺序。如果应用程序中的libraryglidemodule发生冲突,appglidemodule可以使用exclude注释有选择地删除一个或多个冲突模块。
更多
单例模式
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总结