Glide Fetcher


DecodeJob 任务,实现 Runnable 接口,具有状态,关联数据 Fetcher 和回调通知。非内存 Fetcher 时,将该任务分配给合适的线程池 execute(),从 Disk,Res 或 Net 获取。

一、DataFetcherGenerator 流程

DataFetcherGenerator 流程

1,根据任务运行原因,确定状态Stage和数据生产者Generator。

private void runWrapped() {
    switch (runReason) {
        case INITIALIZE:
            //初始阶段是Stage.INITIALIZE
            stage = getNextStage(Stage.INITIALIZE);
            currentGenerator = getNextGenerator();
            runGenerators();
            break;
        case SWITCH_TO_SOURCE_SERVICE:
            runGenerators();
            break;
        case DECODE_DATA:
            decodeFromRetrievedData();
            break;
      default:
         //异常抛出
}

任务可能多次运行,通过 RunReason 表示此次运行原因。

任务运行原因 包括

INITIALIZE
SWITCH_TO_SOURCE_SERVICE
DECODE_DATA

任务创建时,RunReason初始化INITIALIZE,第一次执行runWrapped()方法,初始化Stage和Generator。
任务二次运行SWITCH_TO_SOURCE_SERVICE,从原始数据源获取数据(如网络),使用前次保存的Stage和Generator。

private Stage getNextStage(Stage current) {
    switch (current) {
        case INITIALIZE:
            return diskCacheStrategy.decodeCachedResource()
                    ? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
        case RESOURCE_CACHE:
            return diskCacheStrategy.decodeCachedData()
                    ? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
        case DATA_CACHE:
            return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
        case SOURCE:
        case FINISHED:
            return Stage.FINISHED;
        default:
    }
}

getNextStage()和getNextGenerator()方法,根据上一步当前Stage,初始化下一个状态,同时根据Stage创建Generator。

六种Stage状态

INITIALIZE, //The initial stage
RESOURCE_CACHE, //Decode from a cached resource.
DATA_CACHE, //Decode from cached source data.
SOURCE
ENCODE
FINISHED

Stage DataFetcherGenerator 方式
RESOURCE_CACHE ResourceCacheGenerator 资源文件
DATA_CACHE DataCacheGenerator 缓存
SOURCE SourceGenerator 原始数据源

2,runGenerators()方法,运行Generator。

private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    while (!isCancelled && currentGenerator != null
            && !(isStarted = currentGenerator.startNext())) {
        stage = getNextStage(stage);
        currentGenerator = getNextGenerator();
        //状态变成SOURCE,退出循环。
        if (stage == Stage.SOURCE) {
            reschedule();
            return;
        }
    }
    if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
        notifyFailed();
    }
}

while循环,执行Generator的startNext()方法,返回失败表示未获取数据,继续下一个阶段和生产者,当需要从原始数据源获取时(即状态SOURCE),退出while循环,reschedule()二次运行任务。

@Override
public void reschedule() {
    runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
    callback.reschedule(this);//该DecodeJob任务
}

运行理由转换成SWITCH_TO_SOURCE_SERVICE,Callback即EngineJob,向线程池派发同一个任务对象。

@Override
public void reschedule(DecodeJob job) {
    getActiveSourceExecutor().execute(job);
}

再次运行runWrapped()方法,根据RunReason直接执行runGenerators()方法,Generator即前次已获取的SourceGenerator。

二、DataFetcherGenerator 架构

DataFetcherGenerator 架构

DataSource 数据源

LOCAL ,本地(如 assets )
REMOTE ,远程 (网络)
DATA_DISK_CACHE,本地缓存
RESOURCE_DISK_CACHE ,downsampled 或 transformed 处理过的资源文件
MEMORY_CACHE ,内存

数据 Fetcher
接口 DataFetcher,T类型,内部接口,DataCallback 通知结果,参数是 T类型,Exception 失败 。
loadData() 方法,具体 Fetcher 方法。

index Fetcher Loader
1 HttpUrlFetcher HttpGlideUrlLoader
2 OkHttpStreamFetcher OkHttpUrlLoader
3 Fetcher ByteArrayLoader
4 ByteBufferFetcher ByteBufferFileLoader
5 DataUriFetcher DataUrlLoader
6 FileFetcher FileLoader
7 FilePathFetcher MediaStoreFileLoader
8 ThumbFetcher MediaStoreVideoThumbLoader / MediaStoreImageThumbLoader
9 UnitFetcher UnitModelLoader
10 FileDescriptorAssetPathFetcher,(AssetPathFetcher) AssetUriLoader
11 StreamAssetPathFetcher,(AssetPathFetcher) AssetUriLoader
12 AssetFileDescriptorLocalUriFetcher,(LocalUriFetcher) UriLoader
13 FileDescriptorLocalUriFetcher,(LocalUriFetcher) UriLoader
14 StreamLocalUriFetcher,(LocalUriFetcher) UriLoader
15 MultiFetcher MultiModelLoader

HttpUrlFetcher 和 OkHttpStreamFetcher 的数据源 DataSource 是 REMOTE ,其他都是 LOCAL

MultiFetcher 集成 Fetcher 集合,使用第一项。

根据 model 的 Class 类型,从已注册的 Entry 中,判断标准,model 是 modelClass 本身或子类,由 ModelLoaderFactory 构建支持的 ModelLoader 列表

注册 ModelLoaderRegistry 。

注册的 Model,Data 和 ModelLoaderFactory 。

Model Data ModelLoaderFactory
int InputStream ResourceLoader.StreamFactory
int ParcelFileDescriptor ResourceLoader.FileDescriptorFactory
int Uri ResourceLoader.UriFactory
int AssetFileDescriptor ResourceLoader.AssetFileDescriptorFactory
String InputStream DataUrlLoader.StreamFactory
String InputStream StringLoader.StreamFactory
String ParcelFileDescriptor StringLoader.FileDescriptorFactory
String AssetFileDescriptor StringLoader.AssetFileDescriptorFactory
File ByteBuffer ByteBufferFileLoader.Factory
File InputStream FileLoader.StreamFactory
File ParcelFileDescriptor FileLoader.FileDescriptorFactory
File File UnitModelLoader.Factory
Uri InputStream HttpUriLoader.Factory
Uri InputStream AssetUriLoader.StreamFactory
Uri ParcelFileDescriptor AssetUriLoader.FileDescriptorFactory
Uri InputStream MediaStoreImageThumbLoader.Factory
Uri InputStream MediaStoreVideoThumbLoader.Factory
Uri InputStream UriLoader.StreamFactory
Uri ParcelFileDescriptor UriLoader.FileDescriptorFactory
Uri AssetFileDescriptor UriLoader.AssetFileDescriptorFactory
Uri InputStream UrlUriLoader.StreamFactory
Uri File MediaStoreFileLoader.Factory
Uri Uri UnitModelLoader.Factory
URL InputStream UrlLoader.StreamFactory
GlideUrl InputStream HttpGlideUrlLoader.Factory
Bitmap Bitmap UnitModelLoader.Factory
GifDecoder GifDecoder UnitModelLoader.Factory
byte[] ByteBuffer ByteArrayLoader.ByteBufferFactory
byte[] InputStream ByteArrayLoader.StreamFactory
Drawable Drawable UnitModelLoader.Factory

根据 model,由 Factory 创建 ModelLoader,handle()过滤,判断该 ModelLoader 是否由特殊model。
例如String类 model,仅生成3个StringLoader,DataUrlLoader 只处理data:image开头的String类型。

三、生产者 SourceGenerator

@Override
public boolean startNext() {
    //当已经有了网络数据时,dataToCache不空,存储磁盘缓存中。
    if (dataToCache != null) {
        Object data = dataToCache;
        dataToCache = null;
        cacheData(data);
    }
    //内部Disk缓存生产者,当上一步去cacheData成功后,会初始化该对象。
    if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
        return true;
    }
    sourceCacheGenerator = null;
    loadData = null;
    boolean started = false;
    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;
}

1,从DecodeHelper类中获取LoadData列表,遍历每一项查找匹配LoadData,调用ModelLoader.LoadData内部DataFetcher的loadData()方法。如果Source是远程网路,这里即发起网路请求的位置。
2,DataFetcher接口,内部DataCallback接口数据加载结果回调,Generator实现。
远程网络:LoadData是MultiModelLoader,DataFetcher是MultiFetcher,内部有一个DataFetcher列表,用到OkHttpStreamFetcher的loadData()方法。

public void loadData(@NonNull Priority priority,
                     @NonNull final DataCallback callback) {
    Request.Builder requestBuilder = new Request.Builder().url(url.toStringUrl());
    for (Map.Entry headerEntry : url.getHeaders().entrySet()) {
        String key = headerEntry.getKey();
        requestBuilder.addHeader(key, headerEntry.getValue());
    }
    Request request = requestBuilder.build();
    this.callback = callback;

    call = client.newCall(request);
    call.enqueue(this);//该类实现okhttp回调
}

通过Okhttp的newCall()方法请求,OkHttpStreamFetcher类实现Okhttp的回调Callback,图片下载完成回调,DataCallback接口,生产者SourceGenerator实现DataCallback接口。

@Override
public void onDataReady(Object data) {
    DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
    if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
        //数据保存在内部。
        dataToCache = data;
        cb.reschedule();
    } else {
        cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,
                loadData.fetcher.getDataSource(), originalKey);
    }
}

当Generator执行到onDataReady回调方法时,如果支持Disk缓存,将源数据持久化,将dataToCache保存在Generator内部。FetcherReadyCallback回调,reschedule()方法,再进行一次任务。不支持Disk缓存,onDataFetcherReady()回复。
3,第一次startNext()方法时,dataToCache是空,内部DataCacheGenerator也是空,二次DecodeJob任务数据源不空时,cacheData()方法,数据Disk缓存,同时引用置空,数据被拦截交DataCacheGenerator处理。

四、生产者 DataCacheGenerator

@Override
public boolean startNext() {
    while (modelLoaders == null || !hasNextModelLoader()) {
        sourceIdIndex++;
        if (sourceIdIndex >= cacheKeys.size()) {
            return false;
        }
        Key sourceId = cacheKeys.get(sourceIdIndex);
        Key originalKey = new DataCacheKey(sourceId, helper.getSignature());
        cacheFile = helper.getDiskCache().get(originalKey);
        if (cacheFile != null) {
            this.sourceKey = sourceId;
            modelLoaders = helper.getModelLoaders(cacheFile);
            modelLoaderIndex = 0;
        }
    }
    loadData = null;
    boolean started = false;
    while (!started && hasNextModelLoader()) {
        ModelLoader modelLoader = modelLoaders.get(modelLoaderIndex++);
        loadData =
                modelLoader.buildLoadData(cacheFile, helper.getWidth(), helper.getHeight(),
                        helper.getOptions());
        if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
            started = true;
            //this代表callback
            loadData.fetcher.loadData(helper.getPriority(), this);
        }
    }
    return started;
}

1,查找ModelLoader列表,从cacheKeys列表,获取Key,根据Key查找缓存File,缓存存在时,初始化ModelLoader列表,结束循环,列表一直是空时候会循环多次。
2,根据cacheFile,在列表中匹配ModelLoader,创建LoadData。由内部DataFetcher加载数据。
文件读取:ByteBufferFileLoader实现ModelLoader接口,内部ByteBufferFetcher实现DataFetcher接口。
ByteBufferFetcher的loadData()方法,Data类型ByteBuffer。

@Override
public void loadData(@NonNull Priority priority,
                     @NonNull DataCallback callback) {
    ByteBuffer result;
    try {
        result = ByteBufferUtil.fromFile(file);
    } catch (IOException e) {
        callback.onLoadFailed(e);
        return;
    }
    callback.onDataReady(result);
}

从DataCacheGenerator内部的cacheFile读取ByteBuffer,数据最终交给DecodeJob的onDataFetcherReady()回复。

@Override
public void onDataReady(Object data) {
    cb.onDataFetcherReady(sourceKey, data, loadData.fetcher, DataSource.DATA_DISK_CACHE, sourceKey);
}

五、Generator Callaback

接口 DataFetcherGenerator.FetcherReadyCallback。
DecodeJob实现,Generator构造方法入参数。

@Override
public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher fetcher,
                               DataSource dataSource, Key attemptedKey) {
    this.currentSourceKey = sourceKey;
    this.currentData = data;
    this.currentFetcher = fetcher;
    this.currentDataSource = dataSource;
    this.currentAttemptingKey = attemptedKey;
    //当前线程是否和runGenerators方法时的线程相等。
    if (Thread.currentThread() != currentThread) {
        runReason = RunReason.DECODE_DATA;
        callback.reschedule(this);
    } else {
        TraceCompat.beginSection("DecodeJob.decodeFromRetrievedData");
        try {
            decodeFromRetrievedData();
        } finally {
            TraceCompat.endSection();
        }
    }
}

调用decodeFromRetrievedData()方法。

private void decodeFromRetrievedData() {
    Resource resource = null;
    try {
        resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    } catch (GlideException e) {
        throwables.add(e);
    }
    if (resource != null) {
        notifyEncodeAndRelease(resource, currentDataSource);
    } else {
        runGenerators();
    }
}

decodeFromData()方法,获取Resource结果,notifyEncodeAndRelease()通知。


任重而道远

你可能感兴趣的:(Glide Fetcher)