内容简介:距上篇没看过上篇的小伙伴可以看下
距上篇 Glide 分析的文章已经一个月了,实际分析起来Glide很复杂,对这种复杂进行形容的话,那就是“成吨的复杂”一点也不为过。
没看过上篇的小伙伴可以看下
这个环节,在此之前我们先搞明白,Glide是怎样把图片加载这个过程拆分解耦的。先说结论他的加加载主要分为这样几个过程:
- 加载数据:Model转Data
将复杂不可确定的Model转换成能够直接编码处理的Data,这里对Model包括String Uri URL等就是我们使用Glide.with(this).load(xxx)里面的xxx;Data表示的是能够被编码器识别的数据,包括byte[] 字节数组,InputStream字节流,File文件等等。 - 编码:Data转Resource 这个就是将url String file等通过网络加载文件读取等方式转换最终加载成文件,Bitmap,Drawable,Gif等的过程。
- 转码:Resource 转Resouce 获取到的资源直接能够灵活的转换,包括bitmap转成字节数组,字节数组转成bitmap转Drawable,gif转字节数组等。
去做Model转Data 、Data转Resource、Resource互转工作的类分别是一次分别是ModelLoader<Model, Data> 、ResourceDecoder<T, Z>以及ResourceTranscoder<Z, R> 接口的实现。
另外有了解码也就是从文件、url、等解析成资源的过程也会设计到将Resource转成Flile文件的过程,做这个工作的interface Encoder 接口的实现类。
想必大家都听说过“高内聚,低耦合”,“上层不应该依赖于底层而是应该依赖与抽象”这样的说法。 Glide把刚刚上面我描述的这些功能采用了一种注册机制进行架构。在Glide的这个类构造方法里有这些的代码
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整个系统中的位置,他的实现是怎样的呢。
一、ModelLoader
作用将复杂多变抽象的Mode 如String URL 数据转换为直接被编码的数据如byte[] inputStream等。
具体实现
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<>
二、 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)通知外界。
三、 ModelLoader的生产者,ModelLoaderFactory<T,Y>
我们在往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中的。
四、 DataFetcher生产者 DataFetcherGenerator
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(); } 复制代码
- startNext()方法就是获取一个DataFetcher 并且开始执行获取Data操作,如果开始执行了返回true,否则返回false;
- cancle()取消获取
- FetcherReadyCallback接口供调用者,onDataFetcherReady和onDataFetcherFailed()两个方法见名知意不赘述,值得注意的是onDataFetcherReady()方法有个 Object data参数,他的含义是要 能直接编码的数据Data,这就意味着,当onDataFetcherReady()方法被回调的时候,不但已经穿件了DataFetcher对象,且DataFetcher对象已经获取到了数据Data;
- reschedule()的方法调用它能起的作用是重新执行startNext()方法。
DataFetcherGenerator的集成类有三个
- SourceGenerator (从数据源中获取数据,会设计缓存策略)
- DataCacheGenerator(磁盘获取原始缓存数据)
- ResourceCacheGenerator(磁盘中获取变化过的数据)
在已经注册号的Modlerloader中查找处理
- 在DecodeHelper提供LoadData对象
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; } ... } 复制代码
以SourceGenerater为例
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方法。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
HTTP Essentials
Stephen A. Thomas、Stephen Thomas / Wiley / 2001-03-08 / USD 34.99
The first complete reference guide to the essential Web protocol As applications and services converge and Web technologies not only assume HTTP but require developers to manipulate it, it is be......一起来看看 《HTTP Essentials》 这本书的介绍吧!