Glide Engine


图片加载引擎Engine工作流程

图片引擎加载流程图

一、Engine 引擎

所有图片加载渠道公用,管理Jobs,load()方法,EngineJob,DecodeJob工厂创建。

public <R> LoadStatus load(
        GlideContext glideContext,
        Object model,
        Key signature,
        int width,
        int height,
        ...
        ResourceCallback cb) {
    long startTime = LogTime.getLogTime();
    EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
            resourceClass, transcodeClass, options);
    EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
    if (active != null) {
        cb.onResourceReady(active, DataSource.MEMORY_CACHE);
        return null;
    }
    EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
    if (cached != null) {
        cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
        return null;
    }
    //开始从磁盘或网络获取
    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
        current.addCallback(cb);
        return new LoadStatus(cb, current);
    }
    EngineJob<R> engineJob =
            engineJobFactory.build(
                    key,
                    isMemoryCacheable,
                    useUnlimitedSourceExecutorPool,
                    useAnimationPool,
                    onlyRetrieveFromCache);
    DecodeJob<R> decodeJob =
            decodeJobFactory.build(
                    glideContext,
                    model,
                    key,
                    ...
                    options,
                    engineJob);
    jobs.put(key, engineJob);
    engineJob.addCallback(cb);
    engineJob.start(decodeJob);

    return new LoadStatus(cb, engineJob);
}

1,内存查找
创建EngineKey,若支持内存缓存,首先,loadFromActiveResources方法,根据key在ActiveResources类中获取资源EngineResource。如果不是空,回调,表示从内存获取,否则继续。其次,loadFromCache方法,根据key从MemoryCache中获取,同样支持内存缓存。
返回的Resource<?>类型,可能是EngineResource,不是则包装一下。将cache返回并加入ActiveResources。如果cache不空,依然回调,否则继续。
以上这两种情况都是从内存获取数据,onResourceReady回调方法表明来源是MEMORY_CACHE。
如果在内存缓存中未找到,需要从磁盘缓存或网络中获取。
2,ResourceCallback回调,SingleRequest实现接口,EngineResource类型,来源如MEMORY_CACHE。
3,每个图片请求建立一个引擎任务EngineJob。承接具体load工作,管理记录Jobs。实现DecodeJob.Callback接口。EngineJob保存cb,开始任务。
根据key在Jobs类,获取EngineJob,存在时,直接LoadStatus返回。
EngineJobFactory和DecodeJobFactory工厂分别创建两个Job,EngineJob和DecodeJob。将EngineJob根据key存储在Jobs类。
4,DecodeJob任务,当任务complete,通知DecodeJob.Callback,回调方法,onResourceReady()。
进一步路由到主线程通知到EngineJob的cb即ResourceCallback。

引擎load()流程图

二、EngineJob

实现DecodeJob.Callback接口,交给DecodeJob,任务complete后通知。
EngineJob的start()方法,启动任务。
GlideExecutor线程池,管理线程任务。

DecodeJob是Runnable任务,该任务可以从资源中,文件缓存,或者网络中获取图片。选择一个合适的线程池。

public void start(DecodeJob<R> decodeJob) {
    this.decodeJob = decodeJob;
    GlideExecutor executor = decodeJob.willDecodeFromCache()
        ? diskCacheExecutor
        : getActiveSourceExecutor();
    executor.execute(decodeJob);
}

willDecodeFromCache()方法,判断从Disk或Resource缓存中获取,选择合适的线程池执行任务。将DecodeJob任务派发给它。
内部有四个GlideExecutor线程池,均在GlideBuilder中配置。

boolean willDecodeFromCache() {
    Stage firstStage = getNextStage(Stage.INITIALIZE);
    return firstStage == Stage.RESOURCE_CACHE || firstStage == Stage.DATA_CACHE;
}

在INITIALIZE状态下,下一个Stage将根据DiskCacheStrategy策略类决定,该类默认的decodeCachedResource方法,允许从资源获取图片,Stage设置RESOURCE_CACHE,如果不允许,再判断decodeCachedData方法,从Disk缓存获取图片,Stage设置DATA_CACHE,两者都不允许时,再次执行getNextStage方法,存在onlyRetrieveFromCache标志,说明只能从缓存,而缓存又不存在,只能结束。否则,Stage设置SOURCE。
当Stage是RESOURCE_CACHE或DATA_CACHE时,从依然是从缓存获取。选择的线程池是diskCacheExecutor,如果Stage是Source状态,选择线程池sourceExecutor。还有animationExecutor和sourceUnlimitedExecutor。针对不同的数据源,线程池不同,影响的是每种数据源线程复用的策略。

三、线程耗时任务

线程运行DecodeJob任务,实现Runnable接口,在非内存获取图片资源时,将该任务分配给适当的线程池,从资源,Disk缓存,或网络中获取。

public void run() {
    TraceCompat.beginSection("DecodeJob#run");
    DataFetcher<?> localFetcher = currentFetcher;
    try {
        if (isCancelled) {
            notifyFailed();
            return;
        }
        runWrapped();
    } catch (Throwable t) {
        if (stage != Stage.ENCODE) {
            throwables.add(t);
            notifyFailed();
        }
        if (!isCancelled) {
            throw t;
        }
    } finally {
        if (localFetcher != null) {
            localFetcher.cleanup();
        }
        TraceCompat.endSection();
    }
}

最终在DecodeJob的notifyComplete方法,通过DecodeJob.Callback回调将数据回复到请求EngineJob中,数据包装Resource<>类型。

private void notifyComplete(Resource<R> resource, DataSource dataSource) {
    setNotifiedOrThrow();
    callback.onResourceReady(resource, dataSource);
}

将资源Resource和数据来源DataSource存储在EngineJob,发送消息到主线程处理,转换资源EngineResource子类。
最后ResourceCallback回调,通知外部load方法传入的cb对象。即SingleRequest实现的ResourceCallback接口。

资源通知SingleRequest内部Target。


任重而道远

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。