通过对DataFetcherGenerator的接口方法叙述,仍然没有看懂这个接口到底要做什么,继续看一下在这个接口参数中出现最多的DataFetcher DataSource Key 这个三个类的说明
-
DataFetcher 数据捕捉器
延迟检索可用于加载资源的数据 ModelLoader用来创建一个加载资源的新实例 loadData()或许被调用或者不被调用取决于相应的资源是否被缓存 cancel()或许不被调用,如果loadData()被调用那么cleanup()也会被调用
interface DataFetcher 其中T是被加载数据的类型,一般是InputSteam byte[] File等
interface DataCallback 这个回调必须在数据被加载完成且可获得之后或者加载失败时调用 onDataReady(T data) onLoadFailed(Exception e)
以上 DataFetcher.DataCallback接口就是为了实现对加载完成的数据 T,之后的调用处理,调用DataFetcher.DataCallback 的时机在数据加载完成之后
loadData(Priority priority,DataCallback<? super T> callback)
这个方法在后台子线程中调用,所以阻塞IO是安全的 loadData用来捕获数据通过被解码的资源
因为这个方法在后台执行,所以长时间的运行任务是安全的,任何三方库被调用必须是线程安全的,因为在此方法
是通过ExecutorService调用的,所以可能不只有一个后台子线程,必须保证在请求完成之后使用DataCallback接口
可以将fetch work移动到其他的线程,然后从其他线程Callback ,这个方法只会在相关资源不在cache中才会调用
参数:
Priority是 完成请求的优先级,Callback在请求完成后调用
以上loadData是请求加载数据,是整个任务的开始
cleanup()
cancel()
cleanup是当前请求加载数据之后的finally block,释放或者回收dataFetcher所用的资源,
在loadData通过ResourceDecoder完成对数据解码之后,cleanup在子线程中运行,IO操作安全
cancels是在主线程中操作取消loadData任务,最好是取消还没开始执行的loadData任务
getDataClass():Class<T> 获取Fetcher加载的数据类
getDataSource():DataSource 获取Fetcher加载数据的来源
DataSource是一个enum class 枚举了
Local 表示数据源是本地提供 IO
Remote 表示数据源从远程提供
DataDiskCache 未修改过的缓存
ResourceDiskCache 修改过的缓存
MemoryCache 内存中获取
Key 之后分析
interface ModelLoader<Model,Data> 接口分析
其中 LoadData<Data> 这个类有三个变量组成
Key sourceKey
List<Key> alternateKeys
DataFetcher<Data> fetcher
其中 DataFetcher<Data>是上边讲的 Data的数据加载器,这个data不在缓存中,Key是可以获取到缓存Data的key
buildLoadData():LoadData<Data>
入参是
Model model
int width,height
Option option
其中Model 是加载数据的源Url,高度和宽度是要加载的图片的尺寸,option应该是一些加载的配置
返回的LoadData<Data> 就是直接可以获取到的数据
handle(Model model):Boolean
检验是否当前Model是有效可被识别的类型
综上,ModelLoader<Model,Data>接口内部的两个方法,其实主要是buildLoadData():LoadData,就是实现一个从Model到LoadData转换的类型,但是为什么要把这个过程用接口的方式加泛型Model和Data实现呢
重新回到SourceGenerator中DataFetcherGenerator接口中来分析
startNext(),虽然在叙述中说此方法生成一个DataFetcher,但是返回值只是Boolean表示DataFetcher是否开始执行,那么DataFetcherGenerator如何和DataFetcher发生联系的呢
在SourceGenerator类中
private final DecodeHelper<?> helper;
private final FetcherReadyCallback cb;
private int loadDataListIndex;
private DataCacheGenerator sourceCacheGenerator;
private Object dataToCache;
private volatile ModelLoader.LoadData<?> loadData;
private DataCacheKey originalKey;
上述变量中声明了loadData,在startNext()中由helper.getLoadData().get(loadDataListIndex)
赋值,也就是说loadData由helper:DecodeHelper<?>赋值
来看DecodeHelper这个final class的分析
没有注释...
没有构造方法...
DecodeHelper<Transcode>应该是一个helper类,他的初始化跟随着DecodeJob<R>的初始化开始
decodeHelper的所有参数都是通过DecodeJob传入的,说白了就是一个有变量声明的工具类,
也就是说,loadData对象也是从DecodeHelper传入的,来看一下实现:
glideContext.getRegistry().getModelLoaders(model).each.buildLoadData(
model,
width,height,
option
)
loadData都是通过GlideContext传入的,稍微看了一下全是泛型和反射生成的,太复杂了,先把DecodeHelper的
作用分析清楚
DecodeHelper 方法
getDiskCache()
getDiskCacheStrategy()
getPriority()
getOptions()
getSignature()
getCacheKeys()
getSourceEncoder()
getLoadData()
通过对比DecodeHelper和DecodeJob发现 这两个类有很多方法相同,引用链条很复杂,先缕清这个几个类的引用关系和设计模式
SourceGenerator DecodeHelper DecodeJob
通过分析得 SourceGenerator由DecodeJob初始化,那么分析一下DecodeJob结构
DecodeJob 是一个 implement Runnable,DataFetcherGenerator.FetcherReadyCallback的类
DecodeJob从Run开始分析,发现其内部的流程需要 diskCacheStrategy才能执行下去
diskCacheStrategy磁盘缓存策略
DiskCacheStrategy 类分析:DiskCacheStrategy本身是一个抽象类,内部变量是声明的一个个的继承自DiskCacheStrategy的匿名内部类
DiskCacheStrategy.ALL
DiskCacheStrategy.DATA
DiskCacheStrategy.RESOURCE
DiskCacheStrategy.AUTOMATIC
DiskCacheStrategy.NONE
具体实现有点像 一个enum class枚举类
通过提前配置好的缓存策略来初始化DataFetcherGenerator的类型,有Source,DataCache,ResourceCache这几种 ,之后执行runGenerators() ,在runGenerator内部执行currentGenerator.startNext()
startNext(){
while(!start&&hasNextModelLoader()){
进入内部循环之后,从decodeHelper.获取到loadData,之后startNextLoaded(loadData)
}
}
startNextLoad(LoadData<?>){ loadData.fetcher.loadData()//doSomthing}
LoadData<?>整个流程中最重要的入参,它是如何生成的呢?根据DecodeHelper来分析
List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
loadData = modelLoader.buildLoadData(model, width, height, options);
终于回到GildeContext的Registry这个类中来了
Registry 管理组件注册以扩展和代替Glide默认的加载,解码和编码逻辑
ModelLoaderRegistry
先从接口开始分析 Pools
finalc class Pools {
interface Pool<T> {
T acquire()
boolean release(T instance)
}
Pools 是一个工厂模式的复用池,可以加锁
继续分析FactoryPool
Factory(Pool<T> pool, Factory<T> factory Resetter<T> resetter) implement Pool<T>
其实就是一个包装了Pool的一个可以工厂初始化T对象的,外加可以释放和检验 加锁的 Pool包装类
在Registry中只是一个加锁的列表池 throwableListPool
接着分析MultiModelLoaderFactory
看介绍应该是ModelLoader的工厂包装类
变量如下
throwableListPool
factory