上文说到Glide对请求的准备工作 杨说:Glide 4.11.0 发送请求准备工作 ,这篇分析Glide的请求和缓存。请求最后都是封装成了SingleRequest。
目录
一、请求入口
二、从内存中取图片
三、从磁盘获取取图片
四、从网络获取取图片
五、图片下载成功后回调
六、总结
一 请求入口
request.begin();执行的是SingleRequest的begin()方法
SingleRequest.java
@Override
public void begin() {
//同步锁
synchronized (requestLock) {
···
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
//真正请求和缓存的地方
onSizeReady(overrideWidth, overrideHeight);
} else {
···
}
···
}
}
使用Engine.load()加载图片数据
SingleRequest.java
public void onSizeReady(int width, int height) {
stateVerifier.throwIfRecycled();
synchronized (requestLock) {
if (IS_VERBOSE_LOGGABLE) {
logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
if (status != Status.WAITING_FOR_SIZE) {
return;
}
status = Status.RUNNING;
//缩略图
float sizeMultiplier = requestOptions.getSizeMultiplier();
this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
····
loadStatus =
engine.load(
glideContext,
model,
requestOptions.getSignature(),
this.width,
this.height,
requestOptions.getResourceClass(),
transcodeClass,
priority,
requestOptions.getDiskCacheStrategy(),
requestOptions.getTransformations(),
requestOptions.isTransformationRequired(),
requestOptions.isScaleOnlyOrNoTransform(),
requestOptions.getOptions(),
requestOptions.isMemoryCacheable(),
requestOptions.getUseUnlimitedSourceGeneratorsPool(),
requestOptions.getUseAnimationPool(),
requestOptions.getOnlyRetrieveFromCache(),
this,
callbackExecutor);
···
}
}
首先静态工厂方法创建引擎的key,使用签名,宽度,高度,变换,资源类,配置等作为生成key的参数
Engine.java
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;
//通过静态工厂创建加载引擎的key
EngineKey key =
keyFactory.buildKey(
model,
signature,
width,
height,
transformations,
resourceClass,
transcodeClass,
options);
//从内存中取数据
EngineResource<?> memoryResource;
synchronized (this) {
memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
if (memoryResource == null) {
//
return waitForExistingOrStartNewJob(
glideContext,
model,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
options,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache,
cb,
callbackExecutor,
key,
startTime);
}
}
// Avoid calling back while holding the engine lock, doing so makes it easier for callers to
// deadlock.
cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
return null;
二 从内存中取图片
2.1 从内存中取出图片
memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);从内存中加载图片
Engine.java
private EngineResource<?> loadFromMemory(
EngineKey key, boolean isMemoryCacheable, long startTime) {
//如果设置不从内存中取图片,直接返回null
if (!isMemoryCacheable) {
return null;
}
//获取正在显示的资源
EngineResource<?> active = loadFromActiveResources(key);
if (active != null) {
···
return active;
}
//从缓存中加载图片
EngineResource<?> cached = loadFromCache(key);
if (cached != null) {
···
return cached;
}
return null;
}
2.1.1 从活动的图片中加载图片数据&增加图像引用计数
loadFromActiveResources(key);
Engine.java
private EngineResource<?> loadFromActiveResources(Key key) {
//从缓存中取图像
EngineResource<?> active = activeResources.get(key);
if (active != null) {
//增加引用计数
active.acquire();
}
return active;
}
2.1.1.1 从活动缓存中加载图片数据
ActiveResources.java
synchronized EngineResource<?> get(Key key) {
//弱引用修饰图像引用
ResourceWeakReference activeRef = activeEngineResources.get(key);
if (activeRef == null) {
return null;
}
EngineResource<?> active = activeRef.get();
if (active == null) {
//如果active为null 清空
cleanupActiveReference(activeRef);
}
//返回缓存数据
return active;
}
2.2.1 从缓存中加载图片
loadFromCache(key); 通过可以在缓存中加载图片
Engine.java
private EngineResource<?> loadFromCache(Key key) {
//从缓存重获取图像
EngineResource<?> cached = getEngineResourceFromCache(key);
if (cached != null) {
//增加引用计数
cached.acquire();
//添加到活动的缓存中
activeResources.activate(key, cached);
}
return cached;
}
getEngineResourceFromCache(key);从缓存中获取图像数据
Engine.java
private EngineResource<?> getEngineResourceFromCache(Key key) {
Resource<?> cached = cache.remove(key);
final EngineResource<?> result;
//封装返回结果
if (cached == null) {
result = null;
} else if (cached instanceof EngineResource) {
// Save an object allocation if we've cached an EngineResource (the typical case).
result = (EngineResource<?>) cached;
} else {
result =
new EngineResource<>(
cached, /*isMemoryCacheable=*/ true, /*isRecyclable=*/ true, key, /*listener=*/ this);
}
return result;
}
2.2.2 缓存的初始化
上面获取的缓存是MemoryCache类型的,可以在外部设置,在builder Glide配置时赋值
GlideBuilder.java
@NonNull
Glide build(@NonNull Context context) {
···
if (memoryCache == null) {
//内存缓存
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
}
if (engine == null) {
engine =
new Engine(
//这里将memoryCache传入到加载引擎
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
animationExecutor,
isActiveResourceRetentionAllowed);
}
····
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptionsFactory,
defaultTransitionOptions,
defaultRequestListeners,
isLoggingRequestOriginsEnabled,
isImageDecoderEnabledForBitmaps);
}
2.2.3 内存缓存LruResourceCache
LruResourceCache继承自LruCache,内部使用LinkedHashMap实现LRU算法,初始化大小100,装填因子0.75,所有方法都synchronized修饰保证同步
三 从磁盘中取图片
3.1 创建获取和解码图片任务
从Engine的load方法开始,如果从内存中没有取出图片,那么开始创建任务,从磁盘或者网络上取图片
Engine.java
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) {
memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
if (memoryResource == null) {
return waitForExistingOrStartNewJob(
glideContext,
model,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
options,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache,
cb,
callbackExecutor,
key,
startTime);
}
}
Engine.java
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) {
//如果当前有任务直接取出任务
EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
current.addCallback(cb, callbackExecutor);
···
return new LoadStatus(cb, current);
}
//创建执行的任务
EngineJob<R> engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
//创建解码任务
DecodeJob<R> decodeJob =
decodeJobFactory.build(
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
options,
engineJob);
//将任务添加到缓存中
jobs.put(key, engineJob);
//设置任务的callback
engineJob.addCallback(cb, callbackExecutor);
//开始任务
engineJob.start(decodeJob);
····
return new LoadStatus(cb, engineJob);
}
3.2 engineJob获取图片任务引擎
engineJob是通过工厂方法创建的
GlideBuilder.java
Glide build(@NonNull Conext context) {
···
if (engine == null) {
//如果外部没有设置加载引擎那么直接创建一个
engine =
new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
animationExecutor,
isActiveResourceRetentionAllowed);
}
···
}
Engine构造函数
Engine.java
public Engine(
MemoryCache memoryCache,
DiskCache.Factory diskCacheFactory,
GlideExecutor diskCacheExecutor,
GlideExecutor sourceExecutor,
GlideExecutor sourceUnlimitedExecutor,
GlideExecutor animationExecutor,
boolean isActiveResourceRetentionAllowed) {
this(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
sourceUnlimitedExecutor,
animationExecutor,
/*jobs=*/ null,
/*keyFactory=*/ null,
/*activeResources=*/ null,
/*engineJobFactory=*/ null,
/*decodeJobFactory=*/ null,
/*resourceRecycler=*/ null,
isActiveResourceRetentionAllowed);
}
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) {
···
if (engineJobFactory == null) {
engineJobFactory =
new EngineJobFactory(
diskCacheExecutor,
sourceExecutor,
sourceUnlimitedExecutor,
animationExecutor,
/*engineJobListener=*/ this,
/*resourceListener=*/ this);
}
···
}
3.3 开始获取图片任务
engineJob.start(decodeJob); 开始执行解码的任务,调用的是DecodeJob的run()
EngineJob.java
public synchronized void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor =
decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
executor.execute(decodeJob);
}
DecodeJob.java
public void run() {
···
//赋值callback
DataFetcher<?> localFetcher = currentFetcher;
try {
if (isCancelled) {
notifyFailed();
return;
}
//加载方法
runWrapped();
} catch (CallbackException e) {
// If a callback not controlled by Glide throws an exception, we should avoid the Glide
// specific debug logic below.
throw e;
} catch (Throwable t) {
···
if (stage != Stage.ENCODE) {
throwables.add(t);
notifyFailed();
}
···
} finally {
····
//清空
if (localFetcher != null) {
localFetcher.cleanup();
}
GlideTrace.endSection();
}
}
调用runWrapped();开始执行任务
DecodeJob.java
private void runWrapped() {
switch (runReason) {
//第一次一定会调用这个
case INITIALIZE:
stage = getNextStage(Stage.INITIALIZE);
currentGenerator = getNextGenerator();
runGenerators();
break;
case SWITCH_TO_SOURCE_SERVICE:
runGenerators();
break;
case DECODE_DATA:
decodeFromRetrievedData();
break;
default:
throw new IllegalStateException("Unrecognized run reason: " + runReason);
}
}
getNextStage(Stage.INITIALIZE);根据当前的状态获取加载数据的类型
private Stage getNextStage(Stage current) {
switch (current) {
case INITIALIZE:
//有解码的缓存返回Stage.RESOURCE_CACHE
return diskCacheStrategy.decodeCachedResource()
? Stage.RESOURCE_CACHE
: getNextStage(Stage.RESOURCE_CACHE);
case RESOURCE_CACHE:
//如果有磁盘荤菜返回Stage.DATA_CACHE
return diskCacheStrategy.decodeCachedData()
? Stage.DATA_CACHE
: getNextStage(Stage.DATA_CACHE);
case DATA_CACHE:
// Skip loading from source if the user opted to only retrieve the resource from cache.
//如果只从缓存加载返回Stage.FINISHED否则 Stage.SOURCE
return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
case SOURCE:
case FINISHED:
return Stage.FINISHED;
default:
throw new IllegalArgumentException("Unrecognized stage: " + current);
}
}
getNextStage() 返回Stage到runWrapped(),然后调用getNextGenerator()根据不同的状态获取不同的加载数据的方式
DecodeJob.java
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);
}
}
获取加载数据的方式返回到runWrapped(),调用
DecodeJob.java
private void runGenerators() {
currentThread = Thread.currentThread();
startFetchTime = LogTime.getLogTime();
boolean isStarted = false;
while (!isCancelled
&& currentGenerator != null
//这里就是真正调用加载数据的地方
&& !(isStarted = currentGenerator.startNext())) {
stage = getNextStage(stage);
currentGenerator = getNextGenerator();
if (stage == Stage.SOURCE) {
reschedule();
return;
}
}
····
}
3.4 从磁盘缓存中获取数据
currentGenerator.startNext() 开始获取数据,其中有两个是磁盘的缓存ResourceCacheGenerator从磁盘中获取匹配宽高的缓存、DataCacheGenerator从磁盘中获取缓存
3.4.1 从磁盘中获取匹配宽高的缓存
ResourceCacheGenerator.java
public boolean startNext() {
List<Key> sourceIds = helper.getCacheKeys();
···
List<Class<?>> resourceClasses = helper.getRegisteredResourceClasses();
····
while (modelLoaders == null || !hasNextModelLoader()) {
resourceClassIndex++;
if (resourceClassIndex >= resourceClasses.size()) {
sourceIdIndex++;
if (sourceIdIndex >= sourceIds.size()) {
return false;
}
resourceClassIndex = 0;
}
Key sourceId = sourceIds.get(sourceIdIndex);
Class<?> resourceClass = resourceClasses.get(resourceClassIndex);
//需要转换的类型
Transformation<?> transformation = helper.getTransformation(resourceClass);
// PMD.AvoidInstantiatingObjectsInLoops Each iteration is comparatively expensive anyway,
// we only run until the first one succeeds, the loop runs for only a limited
// number of iterations on the order of 10-20 in the worst case.
//当前缓存的key
currentKey =
new ResourceCacheKey( // NOPMD AvoidInstantiatingObjectsInLoops
helper.getArrayPool(),
sourceId,
helper.getSignature(),
helper.getWidth(),
helper.getHeight(),
transformation,
resourceClass,
helper.getOptions());
//从key中获取文件
cacheFile = helper.getDiskCache().get(currentKey);
if (cacheFile != null) {
sourceKey = sourceId;
modelLoaders = helper.getModelLoaders(cacheFile);
modelLoaderIndex = 0;
}
}
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
ModelLoader<File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
loadData =
modelLoader.buildLoadData(
cacheFile, helper.getWidth(), helper.getHeight(), helper.getOptions());
if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
started = true;
//使用fetcher加载数据
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
3.4.2 从磁盘中获取缓存
DataCacheGenerator.java
public boolean startNext() {
while (modelLoaders == null || !hasNextModelLoader()) {
sourceIdIndex++;
if (sourceIdIndex >= cacheKeys.size()) {
return false;
}
Key sourceId = cacheKeys.get(sourceIdIndex);
// PMD.AvoidInstantiatingObjectsInLoops The loop iterates a limited number of times
// and the actions it performs are much more expensive than a single allocation.
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
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<File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
loadData =
modelLoader.buildLoadData(
cacheFile, helper.getWidth(), helper.getHeight(), helper.getOptions());
if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
started = true;
//从fetcher中加载数据
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
四 从网络获取图片
4.1 从网络获取缓存
currentGenerator.startNext() 开始获取数据,网络的实现类是SourceGenerator
SourceGenerator.java
@Override
public boolean startNext() {
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
cacheData(data);
}
//如果缓存中有直接开始获取数据
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;
//开始网络请求数据
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) {
if (isCurrentRequest(toStart)) {
onDataReadyInternal(toStart, data);
}
}
@Override
public void onLoadFailed(@NonNull Exception e) {
if (isCurrentRequest(toStart)) {
onLoadFailedInternal(toStart, e);
}
}
});
}
loadData.fetcher这个fetcher有很多实现类,网络的实现类是HttpUrlFetcher,调用loadData加载数据
HttpUrlFetcher.java
public void loadData(
@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
long startTime = LogTime.getLogTime();
try {
//使用网络请求默认石使用HttpURLConnection
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
//下载成功调用回调
callback.onDataReady(result);
} catch (IOException e) {
···
//下载失败
callback.onLoadFailed(e);
} finally {
····
}
}
五 图片下载成功后回调
5.1 网络成功回调
SourceGenerator.java
private void startNextLoad(final LoadData<?> toStart) {
loadData.fetcher.loadData(
helper.getPriority(),
new DataCallback<Object>() {
@Override
public void onDataReady(@Nullable Object data) {
if (isCurrentRequest(toStart)) {
//网络请求成功后回调
onDataReadyInternal(toStart, data);
}
}
@Override
public void onLoadFailed(@NonNull Exception e) {
if (isCurrentRequest(toStart)) {
onLoadFailedInternal(toStart, e);
}
}
});
}
SourceGenerator.java
void onDataReadyInternal(LoadData<?> loadData, Object data) {
DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
dataToCache = data;
// We might be being called back on someone else's thread. Before doing anything, we should
// reschedule to get back onto Glide's thread.
cb.reschedule();
} else {
//继续调用回调
cb.onDataFetcherReady(
loadData.sourceKey,
data,
loadData.fetcher,
loadData.fetcher.getDataSource(),
originalKey);
}
}
DecodeJob.java
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;
if (Thread.currentThread() != currentThread) {
//回调到Glide调用线程
runReason = RunReason.DECODE_DATA;
//callback这个是创建DecodeJob的时候传入进来的他是EngineJob,callback
callback.reschedule(this);
} else {
GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
try {
//会调用EngineJob的onResourceReady
decodeFromRetrievedData();
} finally {
GlideTrace.endSection();
}
}
}
DecodeJob.java
private void decodeFromRetrievedData() {
···
Resource<R> resource = null;
try {
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
if (resource != null) {
//调用EngineJob,callback
notifyEncodeAndRelease(resource, currentDataSource);
} else {
runGenerators();
}
}
DecodeJob.java
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
if (resource instanceof Initializable) {
((Initializable) resource).initialize();
}
···
//调用EngineJob,callback
notifyComplete(result, dataSource);
···
}
到这里就调用到了调用EngineJob的onResourceReady方法
DecodeJob.java
private void notifyComplete(Resource<R> resource, DataSource dataSource) {
setNotifiedOrThrow();
callback.onResourceReady(resource, dataSource);
}
EngineJob.java
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
synchronized (this) {
this.resource = resource;
this.dataSource = dataSource;
}
notifyCallbacksOfResult();
}
void notifyCallbacksOfResult() {
···
//调用回调
engineJobListener.onEngineJobComplete(this, localKey, localResource);
for (final ResourceCallbackAndExecutor entry : copy) {
//执行回调
entry.executor.execute(new CallResourceReady(entry.cb));
}
decrementPendingCallbacks();
}
执行CallResourceReadyde run方法
CallResourceReady.java
public void run() {
// Make sure we always acquire the request lock, then the EngineJob lock to avoid deadlock
// (b/136032534).
//加锁
synchronized (cb.getLock()) {
synchronized (EngineJob.this) {
if (cbs.contains(cb)) {
// Acquire for this particular callback.
//增加引用
engineResource.acquire();
callCallbackOnResourceReady(cb);
removeCallback(cb);
}
decrementPendingCallbacks();
}
}
}
EngineJob.java
void callCallbackOnResourceReady(ResourceCallback cb) {
try {
// This is overly broad, some Glide code is actually called here, but it's much
// simpler to encapsulate here than to do so at the actual call point in the
// Request implementation.
cb.onResourceReady(engineResource, dataSource);
} catch (Throwable t) {
throw new CallbackException(t);
}
}
cb.onResourceReady(engineResource, dataSource);这个cb是final ResourceCallbacksAndExecutors cbs = new ResourceCallbacksAndExecutors()。他是一个几个存储监听成功的回调和执行器,他的赋值是在Engine的waitForExistingOrStartNewJob
Engine.java
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) {
EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
//添加回调和执行器
current.addCallback(cb, callbackExecutor);
···
return new LoadStatus(cb, current);
}
EngineJob<R> engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
DecodeJob<R> decodeJob =
decodeJobFactory.build(
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
options,
engineJob);
jobs.put(key, engineJob);
//添加回调和执行器
engineJob.addCallback(cb, callbackExecutor);
engineJob.start(decodeJob);
···
return new LoadStatus(cb, engineJob);
}
这个ResourceCallback类型cb是从Engine的load方法传入的,engine.load()是在SingleRequest中的onSizeReady()调用,并且onSizeReady实现了ResourceCallback
SingleRequest.java
public void onSizeReady(int width, int height) {
stateVerifier.throwIfRecycled();
synchronized (requestLock) {
····
loadStatus =
engine.load(
glideContext,
model,
requestOptions.getSignature(),
this.width,
this.height,
requestOptions.getResourceClass(),
transcodeClass,
priority,
requestOptions.getDiskCacheStrategy(),
requestOptions.getTransformations(),
requestOptions.isTransformationRequired(),
requestOptions.isScaleOnlyOrNoTransform(),
requestOptions.getOptions(),
requestOptions.isMemoryCacheable(),
requestOptions.getUseUnlimitedSourceGeneratorsPool(),
requestOptions.getUseAnimationPool(),
requestOptions.getOnlyRetrieveFromCache(),
//这个this就是ResourceCallback
this,
callbackExecutor);
···
}
}
SingleRequest的onResourceReady
SingleRequest.java
public void onResourceReady(Resource<?> resource, DataSource dataSource) {
stateVerifier.throwIfRecycled();
Resource<?> toRelease = null;
try {
synchronized (requestLock) {
loadStatus = null;
if (resource == null) {
···
//错误
onLoadFailed(exception);
return;
}
Object received = resource.get();
if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
···
onLoadFailed(exception);
return;
}
if (!canSetResource()) {
toRelease = resource;
this.resource = null;
// We can't put the status to complete before asking canSetResource().
status = Status.COMPLETE;
return;
}
//调用处理数据
onResourceReady((Resource<R>) resource, (R) received, dataSource);
}
} finally {
if (toRelease != null) {
engine.release(toRelease);
}
}
}
SingleRequest.java
private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
// We must call isFirstReadyResource before setting status.
boolean isFirstResource = isFirstReadyResource();
//状态成功
status = Status.COMPLETE;
this.resource = resource;
···
isCallingCallbacks = true;
try {
boolean anyListenerHandledUpdatingTarget = false;
if (requestListeners != null) {
for (RequestListener<R> listener : requestListeners) {
anyListenerHandledUpdatingTarget |=
//监听回调完成
listener.onResourceReady(result, model, target, dataSource, isFirstResource);
}
}
anyListenerHandledUpdatingTarget |=
targetListener != null
//调用targetListener成功
&& targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);
if (!anyListenerHandledUpdatingTarget) {
Transition<? super R> animation = animationFactory.build(dataSource, isFirstResource);
//调用target成功,这个target就是我们在外部设置的target
target.onResourceReady(result, animation);
}
} finally {
isCallingCallbacks = false;
}
notifyLoadSuccess();
}
六 总结
1、调用into发送请求加载图片后,会先从内存中取图片,内存中图片会有计数器标记引用数。
2、活动缓存是一个Map<Key,WeakReference>类型,当前View正在显示,内存缓存是LruCache<Key, Resource<?>>类型,最近是否被加入到内存
3、如果内存不存在会从磁盘中取数据,ResourceCacheGenerator是带有宽高尺寸的磁盘缓存,DataCacheGenerator是不带有宽高的磁盘缓存
4、从网络获取数据默认是用HttpUrlConnection,也可以更换成OKHttp