距上篇Glide分析的文章已经一个月了,实际分析起来Glide很复杂,对这种复杂进行形容的话,那就是“成吨的复杂”一点也不为过。
没看过上篇的小伙伴能够看下git
Android图片加载库Glide 知其然知其因此然 开篇 github
去作Model转Data 、Data转Resource、Resource互转工做的类分别是一次分别是ModelLoader<Model, Data> 、ResourceDecoder<T, Z>以及ResourceTranscoder<Z, R> 接口的实现。数组
另外有了解码也就是从文件、url、等解析成资源的过程也会设计到将Resource转成Flile文件的过程,作这个工做的interface Encoder 接口的实现类。缓存
想必你们都据说过“高内聚,低耦合”,“上层不该该依赖于底层而是应该依赖与抽象”这样的说法。 Glide把刚刚上面我描述的这些功能采用了一种注册机制进行架构。在Glide的这个类构造方法里有这些的代码bash
Glide(...){
registry
//将byteBuffer转换为Flile
.append(ByteBuffer.class, new ByteBufferEncoder())
//将inputStream转换为File
.append(InputStream.class, new StreamEncoder(arrayPool))
/* Bitmaps */
//ByteBuffer解码成Bitmap :decoderRegistry
.append(Registry.BUCKET_BITMAP, ByteBuffer.class, Bitmap.class, byteBufferBitmapDecoder)
....
/* BitmapDrawables */
.append(
Registry.BUCKET_BITMAP_DRAWABLE,
ByteBuffer.class,
BitmapDrawable.class,
new BitmapDrawableDecoder<>(resources, byteBufferBitmapDecoder))
/* GIFs */
.append(
Registry.BUCKET_GIF,
InputStream.class,
GifDrawable.class,
new StreamGifDecoder(imageHeaderParsers, byteBufferGifDecoder, arrayPool))
/* Files */
.append(File.class, ByteBuffer.class, new ByteBufferFileLoader.Factory())
FileLoader.FileDescriptorFactory())
// Compilation with Gradle requires the type to be specified for UnitModelLoader here.
.append(File.class, File.class, UnitModelLoader.Factory.<File>getInstance())
/* Models */
.register(new InputStreamRewinder.Factory(arrayPool))
.append(int.class, InputStream.class, resourceLoaderStreamFactory)
.append(
int.class,
ParcelFileDescriptor.class,
resourceLoaderFileDescriptorFactory)
.append(Integer.class, InputStream.class, resourceLoaderStreamFactory)
...
/* Transcoders */
.register(
Bitmap.class,
BitmapDrawable.class,
new BitmapDrawableTranscoder(resources))
.register(Bitmap.class, byte[].class, bitmapBytesTranscoder)
.register(
Drawable.class,
byte[].class,
new DrawableBytesTranscoder(
bitmapPool, bitmapBytesTranscoder, gifDrawableBytesTranscoder))
.register(GifDrawable.class, byte[].class, gifDrawableBytesTranscoder);
}
复制代码
代码实在太长我删减的一部分,整体来说,他就是往里注册了ModuleLoader、Encoder、Decoder、Transcoder这四种组件,使其具有转换模型数据,解析String url等源,解析加载bitmap drawable file用的Decoder,对资源进行转码的Transcoder,以及将资源转成flile的Encoder。这些功能单元都被注册在了Registry,这个类的注释是这样写的,这其中的架构思想你们自行发散思考。网络
Manages component registration to extend or replace Glide's default loading, decoding, and encoding logic.架构
言归正传,这篇咱们着重分析的就是Loading这个过程,抽象的讲就是把复杂的Model(String Url 等)转换成 Data(byte[] InputStream)过程。上面咱们知道了Loading在Glide整个系统中的位置,他的实现是怎样的呢。app
做用将复杂多变抽象的Mode 如String URL 数据转换为直接被编码的数据如byte[] inputStream等。ide
具体实现oop
public interface ModelLoader<Model, Data> {
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);
}
}
/** 给定model 宽高信息 已经Options生成LoadData<?> **/
@Nullable
LoadData<Data> buildLoadData(@NonNull Model model, int width, int height,
@NonNull Options options);
boolean handles(@NonNull Model model);
}
复制代码
生产LoadDate的地方,LoadData里面有个成员变量DataFetcher<>
这个类的对象是加载数据的实际负责人。
public interface DataFetcher<T> {
interface DataCallback<T> {
void onDataReady(@Nullable T data);
void onLoadFailed(@NonNull Exception e);
}
//加载资源文件,这些资源文件多是字节数组,文件等,都是用如今抽象T表明
void loadData(@NonNull Priority priority, @NonNull DataCallback<? super T> callback);
void cleanup();
void cancel();
@NonNull
Class<T> getDataClass();
@NonNull
DataSource getDataSource();
}
复制代码
DataFetcher是一个泛型类,泛型T表示的就是要加载的Data类型。他的功能实现形式是经过回调的,回调接口DataCallback,DataCallback定义了两个方法,onDataReady(T data)和onLoadFailed(Exception e); 见名知意,DataFetcher是获取数据的抽象,他规定了获取Data的时候是经过调用loadData这个方法,这个方法其中有一个参数是DataCallback,当Data获取成功会调用callBack的onDataReady,当获取失败的使时候会调用onLoadFailed(Exception e)通知外界。
咱们在往Registry注册Loader的时候,能够清晰的看到其实往里添加的主要是三个内容Class Class以及ModelLoaderFactory。没错ModelLoaderFactory就是构建ModelLoder的工厂类,前两个参数指明了被处理的数据类型和加载成的数据类型。
.append(File.class, ByteBuffer.class, new ByteBufferFileLoader.Factory())
复制代码
ModelLoaderFactory的代码。
public interface ModelLoaderFactory<T, Y> {
ModelLoader<T, Y> build(@NonNull MultiModelLoaderFactory multiFactory);
void teardown();
}
复制代码
值得注意是是在build方法中传入了MultiModelLoaderFactory一看名字就不简单啊,“多种模型加载工厂”,不贴代码了真相是往Registry对象中注册的ModelLoaderFactory最终都是保存在MultiModelLoaderFactory中的。
interface DataFetcherGenerator {
interface FetcherReadyCallback {
void reschedule();
void onDataFetcherReady(
Key sourceKey, @Nullable Object data,
DataFetcher<?> fetcher,DataSource dataSource,
Key attemptedKey);
void onDataFetcherFailed(Key attemptedKey, Exception e,
DataFetcher<?> fetcher,DataSource dataSource);
}
boolean startNext();
void cancel();
}
复制代码
DataFetcherGenerator的集成类有三个
在已经注册号的Modlerloader中查找处理
DecodeHelper{
...
List<LoadData<?>> getLoadData() {
if (!isLoadDataSet) {
isLoadDataSet = true;
loadData.clear();
List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = modelLoaders.size(); i < size; i++) {
ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
LoadData<?> current =
modelLoader.buildLoadData(model, width, height, options);
if (current != null) {
loadData.add(current);
}
}
}
return loadData;
}
...
}
复制代码
startNext方法
@Override
public boolean startNext() {
//当dataToCache不为空的时候,将dataToCache放入内存中
//而后而后使用sourceCahceGenerator获取Data
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
cacheData(data);
}
if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
sourceCacheGenerator = null;
loadData = null;
boolean started = false;
//获取可以用的LoadData对象,而后调用它的LoadData()
while (!started && hasNextModelLoader()) {
loadData = helper.getLoadData().get(loadDataListIndex++);
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
复制代码
SourceGenerator实现了DataCallBack接口
@Override
public void onDataReady(Object data) {
DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
dataToCache = data;
// We might be being called back on someone else's thread. Before doing anything, we should // reschedule to get back onto Glide's thread.
cb.reschedule();
} else {
cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,
loadData.fetcher.getDataSource(), originalKey);
}
}
复制代码
获取到数据能够被缓存的状况下就会将data赋值给dataToCache,若是不能被赋就回调传入的FetcherReadyCallback对象的onReadyCallback方法。
Model转Data也就是加载数据这个过程设计到单个核心接口类,ModelLoader、LoadData,DataFetcher。 LoadData是ModelLoader这个泛型接口的一个内部类,DataFetcher对象是ModelLoader的一个成员变量。实际将Model转换成Data的工做者就是DataFetcher。
DataFetcher数据加载成功后,采用回调的方式通知调用它的对象。
完。