Engine
由Glide源码分析二——Request相关可知,SingleRequest#onSizeReady(w,h)可知是通过Engine来加载图片的。
Engine是在GlideBuilder#build(context)构造Glide时,new出来传给Glide的。之后在RequestBuilder创建SingleRequest时通过GlideContext.getEngine()获取Engine并传给SingleRequest.
GlideBuilder.java
Glide build(@NonNull Context context) {
...
if (engine == null) {
engine =
new Engine(
memoryCache, // 内存缓存
diskCacheFactory, // 磁盘缓存工厂类
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
animationExecutor,
isActiveResourceRetentionAllowed);
}
...
return new Glide(
...
engine,
...);
}
public class Engine
implements EngineJobListener,
MemoryCache.ResourceRemovedListener,
EngineResource.ResourceListener {
private final Jobs jobs;
private final EngineKeyFactory keyFactory;
private final MemoryCache cache;
private final EngineJobFactory engineJobFactory;
private final ResourceRecycler resourceRecycler;
private final LazyDiskCacheProvider diskCacheProvider;
private final DecodeJobFactory decodeJobFactory;
private final ActiveResources activeResources;
Engine(
MemoryCache cache,
DiskCache.Factory diskCacheFactory,
GlideExecutor diskCacheExecutor,
GlideExecutor sourceExecutor,
GlideExecutor sourceUnlimitedExecutor,
GlideExecutor animationExecutor,
Jobs jobs,
EngineKeyFactory keyFactory,
ActiveResources activeResources,
EngineJobFactory engineJobFactory,
DecodeJobFactory decodeJobFactory,
ResourceRecycler resourceRecycler,
boolean isActiveResourceRetentionAllowed) {
// 二级内存缓存
this.cache = cache;
// 三级磁盘缓存的Provider
this.diskCacheProvider = new LazyDiskCacheProvider(diskCacheFactory);
// 一级内存缓存
if (activeResources == null) {
activeResources = new ActiveResources(isActiveResourceRetentionAllowed);
}
this.activeResources = activeResources;
activeResources.setListener(this);
// 默认的KeyFactory
if (keyFactory == null) {
keyFactory = new EngineKeyFactory();
}
this.keyFactory = keyFactory;
if (jobs == null) {
jobs = new Jobs();
}
this.jobs = jobs;
if (engineJobFactory == null) {
engineJobFactory =
new EngineJobFactory(
diskCacheExecutor,
sourceExecutor,
sourceUnlimitedExecutor,
animationExecutor,
/*engineJobListener=*/ this,
/*resourceListener=*/ this);
}
this.engineJobFactory = engineJobFactory;
if (decodeJobFactory == null) {
decodeJobFactory = new DecodeJobFactory(diskCacheProvider);
}
this.decodeJobFactory = decodeJobFactory;
if (resourceRecycler == null) {
resourceRecycler = new ResourceRecycler();
}
this.resourceRecycler = resourceRecycler;
cache.setResourceRemovedListener(this);
}
public <R> LoadStatus load(
GlideContext glideContext,
Object model,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
Options options,
boolean isMemoryCacheable,
boolean useUnlimitedSourceExecutorPool,
boolean useAnimationPool,
boolean onlyRetrieveFromCache,
ResourceCallback cb,
Executor callbackExecutor) {
long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
EngineKey key =
keyFactory.buildKey(
model,
signature,
width,
height,
transformations,
resourceClass,
transcodeClass,
options);
EngineResource<?> memoryResource;
synchronized (this) {
// 尝试从1、2级缓存中取出资源
memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
if (memoryResource == null) {
// 如果没有内存缓存,则创建EngineJob
return waitForExistingOrStartNewJob(
glideContext,
model,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
options,
isMemoryCacheable, // 从BaseRequestOptions中取,默认是true,除非调用了skipMemoryCache(true)
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache, // 从BaseRequestOptions中取,默认是false
cb,
callbackExecutor, // RequestBuilder#into(...)不传就是在主线程
key,
startTime);
}
}
// 如果有内存缓存则通过回调ResourceCallback#onResourceReady(...)通知SingleRequest资源加载完成,进而通知target加载资源
cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
return null;
}
// 从1、2级缓存中取出资源,关于1、2级缓存可以参考MemoryCache、ActiveResource章节
private EngineResource<?> loadFromMemory(
EngineKey key, boolean isMemoryCacheable, long startTime) {
if (!isMemoryCacheable) {
return null;
}
// 先从一级缓存中取
EngineResource<?> active = loadFromActiveResources(key);
if (active != null) {
return active;
}
// 一级缓存中没有则尝试从二级缓存中取
EngineResource<?> cached = loadFromCache(key);
if (cached != null) {
return cached;
}
return null;
}
// 从一级缓存中取资源
private EngineResource<?> loadFromActiveResources(Key key) {
EngineResource<?> active = activeResources.get(key);
if (active != null) {
// 将EngineResource的引用计数+1,当引用数为0时释放掉
active.acquire();
}
return active;
}
// 从二级缓存中取资源
private EngineResource<?> loadFromCache(Key key) {
EngineResource<?> cached = getEngineResourceFromCache(key);
if (cached != null) {
// 将EngineResource的引用计数+1,当引用数为0时释放掉
cached.acquire();
// 从二级缓存中取到资源后放入一级缓存
activeResources.activate(key, cached);
}
return cached;
}
private EngineResource<?> getEngineResourceFromCache(Key key) {
// 从MemoryCache中取出Resource的同时,也将其从MemoryCache中移除,等到Resource引用数为0时,会再放入MemoryCache
Resource<?> cached = cache.remove(key);
final EngineResource<?> result;
if (cached == null) {
result = null;
} else if (cached instanceof EngineResource) {
// Resource有很多子类,如果是EngineResource则直接返回
result = (EngineResource<?>) cached;
} else {
// 如果不是EngineResource,则包装成EngineResource
result =
new EngineResource<>(
cached, /*isMemoryCacheable=*/ true, /*isRecyclable=*/ true, key, /*listener=*/ this);
}
return result;
}
private <R> LoadStatus waitForExistingOrStartNewJob(
GlideContext glideContext,
Object model,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
Options options,
boolean isMemoryCacheable,
boolean useUnlimitedSourceExecutorPool,
boolean useAnimationPool,
boolean onlyRetrieveFromCache,
ResourceCallback cb,
Executor callbackExecutor,
EngineKey key,
long startTime) {
// 如果当前key已经有对应EngineJob了,则将ResourceCallback和Executor添加到该EngineJob上
EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
current.addCallback(cb, callbackExecutor);
return new LoadStatus(cb, current);
}
// 从EngineJobFactory中获取EngineJob,内部有对象池可复用EngineJob
EngineJob<R> engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
// 和EngineJobFactory一样,内部有对象池
DecodeJob<R> decodeJob =
decodeJobFactory.build(
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
options,
engineJob);
// 将EngineJob放入Jobs中
jobs.put(key, engineJob);
// 将ResourceCallback和Executor添加到该EngineJob上
engineJob.addCallback(cb, callbackExecutor);
// 启动EngineJob
engineJob.start(decodeJob);
return new LoadStatus(cb, engineJob);
}
}
- Resource<Z>包含着真正的资源,例如Bitmap、Drawable、File等,提供了获取资源、资源类class、资源大小、回收资源的方法。
- EngineResource是Resource<Z>的包装类,内部包含引用计数acquire,每次被使用acquire()都会+1,每次被释放release()都会-1,当acquire==0时,会回调通知Engine,从ActiveResources中移除,如果可缓存在内存中则放入MemoryCache,否则回收recycle()。
- DecodeJob是个Runnable,用于从磁盘(SDCard)获取处理后的资源(ResourceCache)、原始资源(ResourceData)、以及从数据源(Source)获取数据。
- EngineJob相当于是管理者,用于管理、监听DecodeJob的执行,当资源加载完成后,会保存资源并通过
EngineJobListener#onEngineJobComplete(EngineJob, Key, engineResource)
通知Engine。
// EngineResource.java
class EngineResource<Z> implements Resource<Z> {
// 是否可缓存在内存中
private final boolean isMemoryCacheable;
// 被包装的资源
private final Resource<Z> resource;
// 引用计数
private int acquired;
// 资源释放回调
interface ResourceListener {
void onResourceReleased(Key key, EngineResource<?> resource);
}
// 回收资源
@Override
public synchronized void recycle() {
// ... 省略部分代码
resource.recycle();
}
// 引用资源
synchronized void acquire() {
// ... 省略部分代码
++acquired;
}
// 释放资源
void release() {
boolean release = false;
synchronized (this) {
// ... 省略部分代码
// 如果引用计数为0,则释放资源
if (--acquired == 0) {
release = true;
}
}
if (release) {
// 回调通知Engine,将资源从ActiveResources中移除,如果资源可缓存在内存中,则放入MemoryCache,否则调用resource#recycle()回收资源
listener.onResourceReleased(key, this);
}
}
}
加载资源流程图.png
资源释放后缓存流程图.png
EngineJob
class EngineJob<R> implements DecodeJob.Callback<R>, Poolable {
public synchronized void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor =
decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
// 使用线程池执行Runnable,decodeJob是个Runnable
executor.execute(decodeJob);
}
synchronized void addCallback(final ResourceCallback cb, Executor callbackExecutor) {
// 添加ResourceCallback和Executor
cbs.add(cb, callbackExecutor);
if (hasResource) {
// 如果资源已经加载好了,则直接调用ResourceCallback#onResourceReady(engineResource, dataSource)通知SingleRequest
incrementPendingCallbacks(1);
callbackExecutor.execute(new CallResourceReady(cb));
} else if (hasLoadFailed) {
// 如果资源已经加载失败了,则通过调用ResourceCallback#onLoadFailed(exception)通知SingleRequest
incrementPendingCallbacks(1);
callbackExecutor.execute(new CallLoadFailed(cb));
} else {
Preconditions.checkArgument(!isCancelled, "Cannot add callbacks to a cancelled EngineJob");
}
}
// 资源加载完成后,EngineJob保存资源,并通过回调通知Engine和SingleRequest
@Override
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
synchronized (this) {
this.resource = resource;
this.dataSource = dataSource;
}
notifyCallbacksOfResult();
}
void notifyCallbacksOfResult() {
ResourceCallbacksAndExecutors copy;
Key localKey;
EngineResource<?> localResource;
synchronized (this) {
stateVerifier.throwIfRecycled();
if (isCancelled) {
// 如果已经取消了,则回收资源并释放EngineJob
resource.recycle();
release();
return;
} else if (cbs.isEmpty()) {
throw new IllegalStateException("Received a resource without any callbacks to notify");
} else if (hasResource) {
throw new IllegalStateException("Already have resource");
}
// 通过factory创建EngineResource,包装resource
engineResource = engineResourceFactory.build(resource, isCacheable, key, resourceListener);
// 设置标志标识已经加载了资源
hasResource = true;
copy = cbs.copy();
incrementPendingCallbacks(copy.size() + 1);
localKey = key;
localResource = engineResource;
}
// 通知Engine EngineJob已经执行完毕
engineJobListener.onEngineJobComplete(this, localKey, localResource);
// 通知SingleRequest资源加载完毕
for (final ResourceCallbackAndExecutor entry : copy) {
entry.executor.execute(new CallResourceReady(entry.cb));
}
decrementPendingCallbacks();
}
// onLoadFailed(GlideException e)和onResourceReady(...)类似,省略
@Override
public void reschedule(DecodeJob<?> job) {
// 在Glide的线程池中重新执行DecodeJob,原因见DecodeJob#reschedule()和DecodeJob#onDataFetcherReady(...)
getActiveSourceExecutor().execute(job);
}
}
DecodeJob
class DecodeJob<R>
implements DataFetcherGenerator.FetcherReadyCallback,
Runnable,
Comparable<DecodeJob<?>>,
Poolable {
private Callback<R> callback; // EngineJob的实例
// 延时缓存数据管理类,内含Encoder和待缓存数据
private final DeferredEncodeManager<?> deferredEncodeManager = new DeferredEncodeManager<>();
public void run() {
DataFetcher<?> localFetcher = currentFetcher;
try {
...
// 根据不同的状态获取不同的DataFetcherGenerator,执行不同的数据加载策略
runWrapped();
} catch (CallbackException e) {
throw e;
} catch (Throwable t) {
...
throw t;
} finally {
// 调用上次加载数据的DataFetcher#cleanup()做一些清除资源的工作,例如HttpUrlFetcher会关闭输入流和连接
if (localFetcher != null) {
localFetcher.cleanup();
}
GlideTrace.endSection();
}
}
// 根据不同的状态获取不同的DataFetcherGenerator,执行不同的数据加载策略
private void runWrapped() {
// DecodeJob在Engine#load(...)中,使用工厂类DecodeJobFactory.build(...)创建时被赋值为INITIALIZE
switch (runReason) {
case INITIALIZE:
//
stage = getNextStage(Stage.INITIALIZE);
currentGenerator = getNextGenerator();
runGenerators();
break;
case SWITCH_TO_SOURCE_SERVICE:
// 如果是从数据源Source获取数据,例如通过SourceGenerator,则会执行rechedule(),此时runReason会置为SWITCH_TO_SOURCE_SERVICE,且currentGenerator还是上次的Generator,应该是SourceGenerator,调用其startNext()会去保存上次获取到的数据,并通过DataCacheGenerator获取待加载数据,详见DataFetcherGenerator章节
runGenerators();
break;
case DECODE_DATA:
decodeFromRetrievedData();
break;
default:
throw new IllegalStateException("Unrecognized run reason: " + runReason);
}
}
// 获取下一个状态
private Stage getNextStage(Stage current) {
switch (current) {
case INITIALIZE:
// 如果可以取磁盘缓存中存储的Resource资源(原始资源处理后的),则返回State.RESOURCE_CACHE,否则返回State.RESOURCE_CACHE的下个状态
return diskCacheStrategy.decodeCachedResource()
? Stage.RESOURCE_CACHE
: getNextStage(Stage.RESOURCE_CACHE);
case RESOURCE_CACHE:
// 如果可以取磁盘缓存中存储的原始资源的话,则返回State.DATA_CACHE,否则返回State.DATA_CACHE的下个状态
return diskCacheStrategy.decodeCachedData()
? Stage.DATA_CACHE
: getNextStage(Stage.DATA_CACHE);
case DATA_CACHE:
// 是否只能从内存中获取资源,是的话则返回结束状态State.FINISHED,否则返回数据源状态State.SOURCE
return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
case SOURCE:
case FINISHED:
return Stage.FINISHED;
default:
throw new IllegalArgumentException("Unrecognized stage: " + current);
}
}
// 根据不同的状态获取对应的DataFetcherGenerator
private DataFetcherGenerator getNextGenerator() {
switch (stage) {
case RESOURCE_CACHE:
return new ResourceCacheGenerator(decodeHelper, this);
case DATA_CACHE:
return new DataCacheGenerator(decodeHelper, this);
case SOURCE:
return new SourceGenerator(decodeHelper, this);
case FINISHED:
return null;
default:
throw new IllegalStateException("Unrecognized stage: " + stage);
}
// 执行Generator#startNext()加载数据,如果返回false说明获取数据失败,则取下个状态的Generator获取数据
private void runGenerators() {
currentThread = Thread.currentThread();
startFetchTime = LogTime.getLogTime();
boolean isStarted = false;
while (!isCancelled
&& currentGenerator != null
&& !(isStarted = currentGenerator.startNext())) {
// 加载失败的话,切换到下一状态和Generator
stage = getNextStage(stage);
currentGenerator = getNextGenerator();
// 如果下个状态时SOURCE的话,则修改runReason为RunReason.SWITCH_TO_SOURCE_SERVICE,并回调到EngineJob中,在线程池中重新执行DecodeJob来获取数据
if (stage == Stage.SOURCE) {
reschedule();
return;
}
}
// 如果所有的状态都尝试了,即所有的Generator都执行了,仍然没有获取到数据,则算作加载失败
if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
notifyFailed();
}
}
// 修改runReason为RunReason.SWITCH_TO_SOURCE_SERVICE,回调到EngineJob中,在Glide线程池中重新执行DecodeJob来加载数据。一般是从数据源Source获取数据时,例如通过SourceGenerator,会执行该方法。当DecodeJob重新执行时,currentGengerator还是上次的generator,一般是SourceGenerator,调用其startNext()会去保存上次获取到的数据,并通过DataCacheGenerator获取待加载数据,详见DataFetcherGenerator章节
public void reschedule() {
runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
// 回调到EngineJob中,在Glide线程池中重新执行DecodeJob来加载数据
callback.reschedule(this);
}
// Generator请求数据成功回调
public void onDataFetcherReady(
Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) {
// 保存得到的数据、以及对应的key、DataFetcher等
this.currentSourceKey = sourceKey;
this.currentData = data;
this.currentFetcher = fetcher;
this.currentDataSource = dataSource;
this.currentAttemptingKey = attemptedKey;
// 如果当前线程不是请求数据时的线程,则回调到EngineJob中切换到Glide线程池中,之后再执行该DecodeJob来完成Decode Data操作
if (Thread.currentThread() != currentThread) {
runReason = RunReason.DECODE_DATA;
callback.reschedule(this);
} else {
// 将请求得到的数据解码成最终结果(transcode类型)并包装成Resource对象
decodeFromRetrievedData();
}
}
// 将请求得到的数据解码成最终结果(transcode类型)并包装成Resource对象
private void decodeFromRetrievedData() {
// 解码,这里得到的是最终结果(transcode类型)的包装类Resource
Resource<R> resource = decodeFromData(currentFetcher, currentData, currentDataSource);
if (resource != null) {
// 解码成功则准备缓存数据
notifyEncodeAndRelease(resource, currentDataSource);
} else {
// 如果解码得到的Resource为null,则重新执行Generator,获取下一个ModelLoader来尝试获取数据(ps:Generator中可能会有多个能够处理model的ModelLoader)
runGenerators();
}
}
// 通知EngineJob数据请求完成、如果有待缓存的数据(已解码完成)则执行缓存,并尝试释放资源
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
...
Resource<R> result = resource;
LockedResource<R> lockedResource = null;
if (deferredEncodeManager.hasResourceToEncode()) {
lockedResource = LockedResource.obtain(resource);
result = lockedResource;
}
// 通知EngineJob数据请求完成
callback.onResourceReady(result, dataSource);
stage = Stage.ENCODE;
try {
// 如果Decoder解码成功,会在onResourceDecoded(DataSource, Resource<Z>)中调用deferredEncodeManager#init(...)保存解码和变换后的数据以及对应的Key和ResourceEncoder,然后在这里进行缓存
if (deferredEncodeManager.hasResourceToEncode()) {
deferredEncodeManager.encode(diskCacheProvider, options);
}
} finally {
if (lockedResource != null) {
lockedResource.unlock();
}
}
// 尝试释放资源
onEncodeComplete();
}
// 解码,这里返回的是最终结果(transcode类型)的包装类Resource
private <Data> Resource<R> decodeFromData(
DataFetcher<?> fetcher, Data data, DataSource dataSource) throws GlideException {
try {
if (data == null) {
// fetcher没有请求到数据
return null;
}
// 获取dataClass的LoadPath,使用其中的Decoder和Transcoder进行解码操作
Resource<R> result = decodeFromFetcher(data, dataSource);
return result;
} finally {
// 执行fetcher的清理工作
fetcher.cleanup();
}
}
// 获取dataClass的LoadPath,使用其中的Decoder和Transcoder进行解码操作
private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource) {
// 获取dataClass的LoadPath
LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
// 使用LoadPath的Decoder和Transcoder进行解码操作
return runLoadPath(data, dataSource, path);
}
// 使用LoadPath的Decoder和Transcoder进行解码操作
private <Data, ResourceType> Resource<R> runLoadPath(
Data data, DataSource dataSource, LoadPath<Data, ResourceType, R> path) {
...
// 获取Registry中注册的DataRewinder,负责将DataClass是Stream类型的数据重置到起始位置
DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
try {
// 使用其中的DecodePath的Decoder和Transcoder进行解码操作,Decoder解码成功后会回调DecodeCallback#onResourceDecoded( Resource<Z> decoded),在该回调中会使用Transformation#transform(...)进行变换操作,之后会调用DeferredEncodeManager.init(...)将变换后的数据保存起来。最后在Transcoder解码完成后会在notifyEncodeAndRelease(...)中调用DeferredEncodeManager#encode(...)缓存变换后的数据TransformedClass。
return path.load(
rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
} finally {
rewinder.cleanup();
}
}
// DecodePath的解码回调
private final class DecodeCallback<Z> implements DecodePath.DecodeCallback<Z> {
private final DataSource dataSource;
@Synthetic
DecodeCallback(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* @params decoded 是Decoder解码得到的数据
* @return 变换后的数据
*/
@Override
public Resource<Z> onResourceDecoded(@NonNull Resource<Z> decoded) {
return DecodeJob.this.onResourceDecoded(dataSource, decoded);
}
}
/**
* Decoder解码完成后触发该方法
* @params decoded 是ResourceDecoder解码得到的数据DecodedClass
* @return 变换后的数据TransformedClass
*/
<Z> Resource<Z> onResourceDecoded(DataSource dataSource, Resource<Z> decoded) {
Class<Z> resourceSubClass = (Class<Z>) decoded.get().getClass();
Transformation<Z> appliedTransformation = null;
Resource<Z> transformed = decoded;
// 如果数据源不是处理后的数据,则利用Transformation#tranform(...)进行变换操作
// 因为数据源可能是通过ResourceCacheGenerator获取的之前缓存的处理(变换)过的数据,这个数据是经过transform的,所以不需要再transform
if (dataSource != DataSource.RESOURCE_DISK_CACHE) {
appliedTransformation = decodeHelper.getTransformation(resourceSubClass);
transformed = appliedTransformation.transform(glideContext, decoded, width, height);
}
...
// 如果Registry中有能够处理tranformed类型的ResourceEncoder,则获取ResourceEncoder和对应的EncodeStrategy,省略该部分代码...
Resource<Z> result = transformed;
// ... 省略根据encodeStrategy生成key的代码
// 将key, encoder, 变换后的数据TransformedClass保存在DeferredEncodeManager中
LockedResource<Z> lockedResult = LockedResource.obtain(transformed);
deferredEncodeManager.init(key, encoder, lockedResult);
result = lockedResult;
return result;
}
}
DocodeJob主要是根据不同的Stage获取不同的DataFetcherGenerator,不同的DataFetcherGenerator可以得到不同的DataFetcher,DataFetcher是用来请求数据的。
获取数据成功之后,会使用DecodePath中保存的Decoder、Transcoder进行解码操作,得到最终数据。
其中Decoder解码成功后会回调DecodeCallback#onResourceDecoded(Resource<Z> decoded),在该回调中会使用Transformation#transform(...)进行变换操作,之后会调用DeferredEncodeManager#init(...)将变换后的数据保存起来。 最后在Transcoder解码完成后会在notifyEncodeAndRelease(...)中调用DeferredEncodeManager#encode(...)缓存变换后的数据。
DataFetcherGenerator
DataFetcherGenerator有3个子类,逐级尝试获取数据:
- ResourceCacheGenerator,从磁盘缓存中获取原始资源处理后的Resource资源
- DataCacheGenerator,从磁盘缓存中获取原始资源
- SourceGenerator,从数据源(例如网络)中获取资源
这里分析下ResourceCacheGenerator吧:
// ResourceCacheGenerator.java
private Object model;
// 实例是LazyDiskCacheProvider,在Engine中设置给DecodeJobFactory,之后的传递路径是DecodeJobFactory -> DecodeJob -> DecodeHelper。实例是LazyDiskCacheProvider,内部包含一个DiskCache.Factory,实例是InternalCacheDiskCacheFactory,它的build()方法会创建DiskLruCacheWrapper,是一个DiskLruCache的包装类。
private DecodeJob.DiskCacheProvider diskCacheProvider;
// 当前缓存资源对应的key
private Key sourceKey;
// 资源请求回调
private final FetcherReadyCallback cb;
private final DecodeHelper<?> helper;
ResourceCacheGenerator(DecodeHelper<?> helper, FetcherReadyCallback cb) {
this.helper = helper;
this.cb = cb;
}
// 开始获取缓存,获取成功返回true,失败返回false
public boolean startNext() {
// Registry在Engine中初始化后,添加了很多输入类型(ModelClass),输出类型(DataClass),以及对应的ModelLoaderFactory,并封装成Entry放入MultiModelLoaderFactory中。
// 这里通过DecodeHelper获取能够处理model的Entry,并用Entry中的ModelLoaderFactory创建对应的ModelLoader,然后用ModelLoader创建LoadData,之后返回LoadData的sourceKey和alternateKeys
List<Key> sourceIds = helper.getCacheKeys();
if (sourceIds.isEmpty()) {
return false;
}
// ...
while (modelLoaders == null || !hasNextModelLoader()) {
resourceClassIndex++;
if (resourceClassIndex >= resourceClasses.size()) {
sourceIdIndex++;
if (sourceIdIndex >= sourceIds.size()) {
return false;
}
resourceClassIndex = 0;
}
Key sourceId = sourceIds.get(sourceIdIndex);
// ...
// DiskLruCache的key
currentKey =
new ResourceCacheKey( // NOPMD AvoidInstantiatingObjectsInLoops
helper.getArrayPool(),
sourceId,
helper.getSignature(),
helper.getWidth(),
helper.getHeight(),
transformation,
resourceClass,
helper.getOptions());
// 利用DecodeHelper获取DiskLruCacheWrapper,它是diskLruCache的包装类,之后根据key获取缓存文件
cacheFile = helper.getDiskCache().get(currentKey);
if (cacheFile != null) {
sourceKey = sourceId;
// 以缓存文件为输入model获取ModelLoader
modelLoaders = helper.getModelLoaders(cacheFile);
modelLoaderIndex = 0;
}
}
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
ModelLoader<File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
// 利用ModelLoader构建LoadData
loadData =
modelLoader.buildLoadData(
cacheFile, helper.getWidth(), helper.getHeight(), helper.getOptions());
// 如果loadData对应的dataClass有加载路径LoadPath,说明可以从数据源解码得到最终数据,则利用DataFetcher请求数据
if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
started = true;
// 利用DataFetcher请求数据
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
private boolean hasNextModelLoader() {
return modelLoaderIndex < modelLoaders.size();
}
@Override
public void onDataReady(Object data) {
// 当数据加载完成后,会回调通知DecodeJob,onLoadFailed()类似。
cb.onDataFetcherReady(
sourceKey, data, loadData.fetcher, DataSource.RESOURCE_DISK_CACHE, currentKey);
}
DataCacheGenerator和SourceCacheGenerator也差不多,只是SourceCacheGenerator获取到数据之后会根据Engine#load(...)中设置的diskCacheStrategy来缓存数据。
// SourceCacheGenerator.java
// 待存储的数据(上次获取的数据)
private Object dataToCache;
private volatile ModelLoader.LoadData<?> loadData;
public boolean startNext() {
// 如果有待存储的数据,则先存储数据
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
// 存储数据,存储完成后会创建DataCacheGenerator,之后就是通过DataCacheGenerator获取待加载数据
cacheData(data);
}
// 如果不为null则说明之前存储了数据,存储完成后通过DataCacheGenerator来获取待加载数据,获取成功则return,后面会在onDataFetcherReady(...)通知DecodeJob
if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
// 如果之前没有存储数据,或者有存储数据,但是DataCacheGenerator获取待加载数据失败,则通过DataFetcher获取数据
sourceCacheGenerator = null;
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
// 获取能够处理model的ModelLoader,从而buildLoadData,返回能够根据model获取数据的LoadDatas
loadData = helper.getLoadData().get(loadDataListIndex++);
// 1.如果根据磁盘缓存策略DiskCacheStrategy和LoadData的Fetcher对应的DataSource,表明获取的数据是可以缓存的,或者2.如果获取的数据有对应的加载路径LoadPath,则通过该LoadData的Fetcher获取数据
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
// 使用Fetcher获取数据
startNextLoad(loadData);
}
}
return started;
}
private void startNextLoad(final LoadData<?> toStart) {
loadData.fetcher.loadData(
helper.getPriority(),
new DataCallback<Object>() {
@Override
public void onDataReady(@Nullable Object data) {
// 如果Generator请求数据用的LoadData就是当前请求所使用的LoadData,说明是同一个请求
if (isCurrentRequest(toStart)) {
onDataReadyInternal(toStart, data);
}
}
@Override
public void onLoadFailed(@NonNull Exception e) {
if (isCurrentRequest(toStart)) {
onLoadFailedInternal(toStart, e);
}
}
});
}
void onDataReadyInternal(LoadData<?> loadData, Object data) {
DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
// 如果根据磁盘缓存策略DiskCacheStrategy和LoadData的Fetcher对应的DataSource,表明获取的数据是可以缓存的,则在Glide的线程池中重新执行DecodeJob,之后会重新执行该Generator,可以查看DecodeJob章节进行验证该逻辑
if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
// 暂存数据,reschedule()之后会重新执行SourceGenerator#startNext(),数据会在其中进行保存
dataToCache = data;
cb.reschedule();
} else {
cb.onDataFetcherReady(
loadData.sourceKey,
data,
loadData.fetcher,
loadData.fetcher.getDataSource(),
originalKey);
}
}
// 缓存数据
private void cacheData(Object dataToCache) {
long startTime = LogTime.getLogTime();
try {
// 根据待缓存数据的Class,获取Registry在Glide中添加的Encoder
Encoder<Object> encoder = helper.getSourceEncoder(dataToCache);
// 这是一个包装类,包含待缓存数据、Encoder和Options,之后在DiskLruCacheWrapper中拿到缓存文件后,调用DataCacheWriter#write(file),其实就是调用Encoder#encode(data, file, options)通过输出流将数据写入缓存文件
DataCacheWriter<Object> writer =
new DataCacheWriter<>(encoder, dataToCache, helper.getOptions());
originalKey = new DataCacheKey(loadData.sourceKey, helper.getSignature());
// 利用DecodeHelper获取DiskLruCacheWrapper,它是DiskLruCache的包装类,然后将数据放入originalKey对应的缓存文件中
helper.getDiskCache().put(originalKey, writer);
} finally {
// 释放DataFetcher中的资源
loadData.fetcher.cleanup();
}
// 创建DataCacheGenerator,一会会通过DataCacheGenerator获取待加载的数据
sourceCacheGenerator =
new DataCacheGenerator(Collections.singletonList(loadData.sourceKey), helper, this);
}
DataCacheWriter是个包装类,实际还是通过Encoder在缓存数据的:
// DataCacheWriter.java
class DataCacheWriter<DataType> implements DiskCache.Writer {
private final Encoder<DataType> encoder;
private final DataType data;
private final Options options;
DataCacheWriter(Encoder<DataType> encoder, DataType data, Options options) {
this.encoder = encoder;
this.data = data;
this.options = options;
}
// 在在DiskLruCacheWrapper中拿到缓存文件后,调用该方法
@Override
public boolean write(@NonNull File file) {
return encoder.encode(data, file, options);
}
}
随便看一个Encoder的实现吧:
public class StreamEncoder implements Encoder<InputStream> {
public boolean encode(@NonNull InputStream data, @NonNull File file, @NonNull Options options) {
byte[] buffer = byteArrayPool.get(ArrayPool.STANDARD_BUFFER_SIZE_BYTES, byte[].class);
boolean success = false;
OutputStream os = null;
try {
// 将输入流写入到缓存文件
os = new FileOutputStream(file);
int read;
while ((read = data.read(buffer)) != -1) {
os.write(buffer, 0, read);
}
os.close();
success = true;
} catch (IOException e) {
} finally {
// ... close stream
}
return success;
}
}
LoadPath、DecodePath
由DecodeJob章节可以知道,通过Generator获取数据成功后,会通过LoadPath/DecodePath进行解码。
几个类的理解:
- LoadPath,可以这么理解:顾名思义,加载路径,从dataClass得到resourceClass,从而得到transcodeClass,内部包含dataClass、resourceClass、transcodeClass以及decodePath
- DecodePath,可以这么理解:顾名思义,解码路径,内部包含ResourceDecoder和ResourceTranscoder,以及DataClass、ResourceClass、TranscodeClass,利用ResourceDecoder可以将DataClass转化为ResourceClass,利用TranscodeClass可以将ResrouceClass转化为TranscodeClass
// LoadPath.java
public class LoadPath<Data, ResourceType, Transcode> {
// 该LoadPath对应的dataClass
private final Class<Data> dataClass;
// 实际进行解码操作的是DecodePath
private final List<? extends DecodePath<Data, ResourceType, Transcode>> decodePaths;
public Resource<Transcode> load(
DataRewinder<Data> rewinder,
Options options,
int width,
int height,
DecodePath.DecodeCallback<ResourceType> decodeCallback) {
List<Throwable> throwables = Preconditions.checkNotNull(listPool.acquire());
...
// 利用DecodePath中的Decoder、Transcoder进行解码
return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);
...
}
// 利用DecodePath中的Decoder、Transcoder进行解码
private Resource<Transcode> loadWithExceptionList(
DataRewinder<Data> rewinder,
Options options,
int width,
int height,
DecodePath.DecodeCallback<ResourceType> decodeCallback,
List<Throwable> exceptions) {
Resource<Transcode> result = null;
for (int i = 0, size = decodePaths.size(); i < size; i++) {
DecodePath<Data, ResourceType, Transcode> path = decodePaths.get(i);
// 使用DecodePath进行解码
result = path.decode(rewinder, width, height, options, decodeCallback);
if (result != null) {
break;
}
}
return result;
}
}
LoadPath相当于代理类,内部使用DecodePath来完成解码操作。
// DecodePath.java
public class DecodePath<DataType, ResourceType, Transcode> {
// DecodePath对应的dataClass
private final Class<DataType> dataClass;
// 能够将dataClass转换为ResourceClass的ResourceDecoder
private final List<? extends ResourceDecoder<DataType, ResourceType>> decoders;
// 能够将ResourceClass转换为TranscodeClass的ResourceTranscoder
private final ResourceTranscoder<ResourceType, Transcode> transcoder;
// 解码操作
public Resource<Transcode> decode(
DataRewinder<DataType> rewinder,
int width,
int height,
Options options,
DecodeCallback<ResourceType> callback)
throws GlideException {
// 使用ResourceDecoder将DataClass转换为ResourceClass
Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
// 回调到DecodeJob中,利用Trasformation对ResourceClass进行变换操作
Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
// 使用ResourceTranscoder将变换后的资源转换为最终结果
return transcoder.transcode(transformed, options);
}
private Resource<ResourceType> decodeResource(
DataRewinder<DataType> rewinder, int width, int height, @NonNull Options options)
throws GlideException {
...
return decodeResourceWithList(rewinder, width, height, options, exceptions);
...
}
private Resource<ResourceType> decodeResourceWithList(
DataRewinder<DataType> rewinder,
int width,
int height,
@NonNull Options options,
List<Throwable> exceptions) {
Resource<ResourceType> result = null;
for (int i = 0, size = decoders.size(); i < size; i++) {
ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);
// 使用DataRewinder将数据类型为Stream类型的数据重置到起始位置,并返回数据
DataType data = rewinder.rewindAndGet();
// 如果该decoder能够处理data,则使用decoder进行解码
if (decoder.handles(data, options)) {
data = rewinder.rewindAndGet();
result = decoder.decode(data, width, height, options);
}
if (result != null) {
break;
}
}
return result;
}
}
DeferredEncodeManager<Z>
由DecodeJob章节可以知道,数据解码成功后,会通过DeferredEncodeManager进行缓存,它是DecodeJob的内部类。
它其实是个辅助类,实际的缓存工作是由ResourceEncoder完成的。
private static class DeferredEncodeManager<Z> {
private Key key;
// 缓存数据的ResourceEncoder
private ResourceEncoder<Z> encoder;
// 待缓存的数据
private LockedResource<Z> toEncode;
// ResourceDecoder解码原始数据后,在DecodeJob#onResourceDecoded(DataSource dataSource, Resource<Z> decoded)方法中调用,保存待缓存数据(处理(变换)后的数据DecodedClass/TransformedClass,不是最终数据TranscodedClass)和对应的key以及ResourceEncoder
<X> void init(Key key, ResourceEncoder<X> encoder, LockedResource<X> toEncode) {
this.key = key;
this.encoder = (ResourceEncoder<Z>) encoder;
this.toEncode = (LockedResource<Z>) toEncode;
}
// ResourceTranscoder解码DecodedClass/TransformedClass后,在DecodeJob#notifyEncodeAndRelease(...)中调用,进行缓存DecodedClass/TransformedClass
void encode(DiskCacheProvider diskCacheProvider, Options options) {
GlideTrace.beginSection("DecodeJob.encode");
try {
// 获取DiskLruCacheWrapper,并构建DataCacheWriter用于缓存文件,具体参考DataFetcherGenerator章节Encoder缓存数据相关内容
diskCacheProvider
.getDiskCache()
.put(key, new DataCacheWriter<>(encoder, toEncode, options));
} finally {
toEncode.unlock();
GlideTrace.endSection();
}
}
boolean hasResourceToEncode() {
return toEncode != null;
}
}
DecodeHelper
DecodeHelper是一个辅助类,每个DecodeJob对应一个DecodeHelper,在DecodeJob#init(...)中进行初始化,为DecodeJob提供能够处理Model的ModelLoader、LoadData和对应的Key、DiskCache、DiskCacheStrategy、LoadPath、Transformation、以及缓存数据用的Encoder等。
final class DecodeHelper<Transcode> {
private final List<LoadData<?>> loadData = new ArrayList<>();
private final List<Key> cacheKeys = new ArrayList<>();
private GlideContext glideContext;
private Object model;
private int width;
private int height;
private Class<?> resourceClass;
private DecodeJob.DiskCacheProvider diskCacheProvider; // Engine中初始化了LazyDiskCacheProvider,传给DecodeJobFactory->DecodeJob->DecodeHelper
private Options options;
private Map<Class<?>, Transformation<?>> transformations;
private Class<Transcode> transcodeClass;
private DiskCacheStrategy diskCacheStrategy;
// 在DecodeJob#init(...)中调用进行初始化
<R> void init(
GlideContext glideContext,
Object model,
Key signature,
int width,
int height,
DiskCacheStrategy diskCacheStrategy,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
Options options,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
DiskCacheProvider diskCacheProvider) {
this.glideContext = glideContext;
this.model = model;
this.signature = signature;
this.width = width;
this.height = height;
this.diskCacheStrategy = diskCacheStrategy;
this.resourceClass = resourceClass;
this.diskCacheProvider = diskCacheProvider; // 实例是LazyDiskCacheProvider,在Engine中设置给DecodeJobFactory,之后的传递路径是DecodeJobFactory -> DecodeJob -> DecodeHelper。
this.transcodeClass = (Class<Transcode>) transcodeClass;
this.priority = priority;
this.options = options;
this.transformations = transformations;
this.isTransformationRequired = isTransformationRequired;
this.isScaleOnlyOrNoTransform = isScaleOnlyOrNoTransform;
}
// 获取DiskCache,它有两个子类,一个是DiskCacheAdapter(空实现),一个是DiskLruCacheWrapper(DiskLruCache的包装类)
DiskCache getDiskCache() {
return diskCacheProvider.getDiskCache();
}
// 获取磁盘缓存策略,用于判断请求结果(包括原始数据和处理后的数据)是否可以缓存,详见DiskCacheStrategy章节
DiskCacheStrategy getDiskCacheStrategy() {
return diskCacheStrategy;
}
// 获取返回结果的Class,例如BitmapDrawable
Class<?> getTranscodeClass() {
return transcodeClass;
}
// 获取请求参数的Class,例如RequestManager#load(String url),ModelClass就是Strin.class
Class<?> getModelClass() {
return model.getClass();
}
// 中间类型,从数据源返回的类型Data编码成的类型,例如Bitmap、Drawable、GifDrawable、BitmapDrawable、File等。举个例子:例如由InputStream编码成Bitmap。可以参考Engine的构造函数中,Registry#append(...)添加的类型。
List<Class<?>> getRegisteredResourceClasses() {
return glideContext
.getRegistry()
.getRegisteredResourceClasses(model.getClass(), resourceClass, transcodeClass);
}
// 是否有符合从DataClass->ResourceClass->TranscodeClass的LoadPath
boolean hasLoadPath(Class<?> dataClass) {
return getLoadPath(dataClass) != null;
}
// 获取从DataClass->ResourceClass->TranscodeClass的LoadPath
<Data> LoadPath<Data, ?, Transcode> getLoadPath(Class<Data> dataClass) {
return glideContext.getRegistry().getLoadPath(dataClass, resourceClass, transcodeClass);
}
// 获取能够以缓存文件file为输入得到数据的ModelLoader
List<ModelLoader<File, ?>> getModelLoaders(File file)
throws Registry.NoModelLoaderAvailableException {
return glideContext.getRegistry().getModelLoaders(file);
}
// 获取能够以Model为输入得到数据的LoadData
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;
}
// 获取能够以Model为输入得到数据的LoadData对应的Key
List<Key> getCacheKeys() {
if (!isCacheKeysSet) {
isCacheKeysSet = true;
cacheKeys.clear();
List<LoadData<?>> loadData = getLoadData();
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = loadData.size(); i < size; i++) {
LoadData<?> data = loadData.get(i);
if (!cacheKeys.contains(data.sourceKey)) {
cacheKeys.add(data.sourceKey);
}
for (int j = 0; j < data.alternateKeys.size(); j++) {
if (!cacheKeys.contains(data.alternateKeys.get(j))) {
cacheKeys.add(data.alternateKeys.get(j));
}
}
}
}
return cacheKeys;
}
// 获取能够缓存data的Encoder
<X> Encoder<X> getSourceEncoder(X data) throws Registry.NoSourceEncoderAvailableException {
return glideContext.getRegistry().getSourceEncoder(data);
}
}
ModelLoader、LoadData、DataFetcher
这三个类主要是用于根据model请求数据的。
三者的UML图如下:
Registry、ModelLoader、LoadData、DataFetcher关系图.png
在Glide章节中,我们知道Registry注册了很多Entry,其中包括注册了ModelLoaderFactory,而这个ModelLoaderFactory最终会被包装成Entry,保存在MultiModelLoaderFactory中:
// Glide.java
registry.append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())
// Registry.java
public <Model, Data> Registry append(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<Model, Data> factory) {
modelLoaderRegistry.append(modelClass, dataClass, factory);
return this;
}
// ModelLoaderRegistry.java
public synchronized <Model, Data> void append(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
multiModelLoaderFactory.append(modelClass, dataClass, factory); // 1
cache.clear();
}
// MultiModelLoaderFactory.java
private final List<Entry<?, ?>> entries = new ArrayList<>();
synchronized <Model, Data> void append(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
add(modelClass, dataClass, factory, /*append=*/ true); // 2
}
private <Model, Data> void add(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory,
boolean append) {
Entry<Model, Data> entry = new Entry<>(modelClass, dataClass, factory);
entries.add(append ? entries.size() : 0, entry); // 3
}
之后在DecodedJob中,我们知道,请求数据是由DataFetcherGenerator完成的,具体可以参考DecodeJob和DataFetcherGenerator章节。
而DataFetcherGenerator则是通过DecodeHelper获取Registry中注册的能够处理model的Entry的ModelLoaderFactory,从而build出ModelLoader,进而得到LoadData。
例如SourceGenerator,这里只展示部分代码,具体灿开DataFetcherGenerator章节。
// SourceGenerator.java
public boolean startNext() {
...
// 1. 通过DecodeHelper获取LoadData
loadData = helper.getLoadData().get(loadDataListIndex++);
...
}
// DecodeHelper.java
List<LoadData<?>> getLoadData() {
...
// 2. 获取Registry中注册的能够处理model的Entry,并用其中的ModelLoaderFactory创建ModelLoader
List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
...
// 3. 通过ModelLoader创建LoadData
ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
LoadData<?> current = modelLoader.buildLoadData(model, width, height, options);
...
}
得到LoadData之后,就会用其中的DataFetcher请求数据,具体可以参考DataFetcherGenerator章节。
这里简单看下HttpGlideUrlLoader,以及对应的Factory和Fetcher吧:
// HttpGlideUrlLoader.java
public class HttpGlideUrlLoader implements ModelLoader<GlideUrl, InputStream> {
// 返回LoadData,内部包含实际进行请求的Fetcher
@Override
public LoadData<InputStream> buildLoadData(GlideUrl model, int width, int height, Options options) {
return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
}
// 用于判断当前ModelLoader是否可以处理model。
// 例如UrlUriModelLoader判断是否可以处理model的条件是uri的schema是否是http或https
@Override
public boolean handles(GlideUrl model) {
return true;
}
// 创建该ModelLoader的ModelLoaderFactory
public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
// 创建ModelLoader
public ModelLoader<GlideUrl, InputStream> build(MultiModelLoaderFactory multiFactory) {
return new HttpGlideUrlLoader(modelCache);
}
}
}
真正实现请求的是DataFetcher:
// HttpUrlFetcher.java
// HttpUrlFetcher的model是GlideUrl,data是InputStream
public class HttpUrlFetcher implements DataFetcher<InputStream> {
private final GlideUrl glideUrl;
// 工厂类,用于创建HttpURLConnection
private final HttpUrlConnectionFactory connectionFactory;
private HttpURLConnection urlConnection;
// 请求得到的数据
private InputStream stream;
public void loadData(Priority priority, DataCallback<? super InputStream> callback) {
try {
// 执行请求,得到数据数据流
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
// 回调通知DataFetcherGenerator或MultiModelLoader
callback.onDataReady(result);
} catch (IOException e) {
callback.onLoadFailed(e);
}
}
// 执行请求,得到数据数据流
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl, Map<String, String> headers) {
// ... 省略一些抛异常的代码
// 通过工厂类创建HttpURLConnection,例如url.openConnection()
urlConnection = connectionFactory.build(url);
// ... 省略一些给urlConnection设置header、timeout等参数的代码
// 请求服务器
urlConnection.connect();
// 获取输入流,以便在cleanup()中关闭,避免(ResponseBody)资源泄漏?
stream = urlConnection.getInputStream();
if (isCancelled) {
return null;
}
// 响应码
final int statusCode = urlConnection.getResponseCode();
if (isHttpOk(statusCode)) {
// 请求成功,则从连接获取输入流
return getStreamForSuccessfulRequest(urlConnection);
} else if (isHttpRedirect(statusCode)) {
// ... 省略重定向相关代码
} else if (statusCode == INVALID_STATUS_CODE) {
// 无法识别的错误码,请求失败
throw new HttpException(statusCode);
} else {
// 请求失败
throw new HttpException(urlConnection.getResponseMessage(), statusCode);
}
}
private static boolean isHttpOk(int statusCode) {
return statusCode / 100 == 2;
}
private static boolean isHttpRedirect(int statusCode) {
return statusCode / 100 == 3;
}
// 从连接获取输入流
private InputStream getStreamForSuccessfulRequest(HttpURLConnection urlConnection) {
if (TextUtils.isEmpty(urlConnection.getContentEncoding())) {
// ContentEncoding为空,说明返回的是未压缩的响应正文,则Response中的响应头包含ContentLength!=-1
int contentLength = urlConnection.getContentLength();
stream = ContentLengthInputStream.obtain(urlConnection.getInputStream(), contentLength);
} else {
// ContentEncoding不为空,说明返回的是压缩过的响应正文,ContentLength==-1,则直接获取数据流,之后需要用ContentEncoding的编码格式进行解码,例如gzip
stream = urlConnection.getInputStream();
}
return stream;
}
// 执行资源清理工作
@Override
public void cleanup() {
if (stream != null) {
stream.close();
}
if (urlConnection != null) {
urlConnection.disconnect();
}
urlConnection = null;
}
// 取消请求数据操作
@Override
public void cancel() {
isCancelled = true;
}
}
得到DataFetcher后,会包装成LoadData,它是一个包装类,其实啥也没干,位于ModelLoader的内部类:
// ModelLoader.java
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 List<Key> alternateKeys,
@NonNull DataFetcher<Data> fetcher) {
this.sourceKey = Preconditions.checkNotNull(sourceKey);
this.alternateKeys = Preconditions.checkNotNull(alternateKeys);
this.fetcher = Preconditions.checkNotNull(fetcher);
}
}
}
网友评论