接着 DataFetcherGenerator接口分析

318 阅读5分钟

通过对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