Glide 源码阅览笔记(五)
在榜首篇文章中我简略介绍了Glide
实例的创立进程,要点介绍了Glide
的内存缓存完结和磁盘的缓存完结:Glide 源码阅览笔记(一)
在第二篇文章中介绍了Glide
对生命周期的办理:Glide 源码阅览笔记(二)
在第三篇文章中介绍了 Request
和 RequestCoordinator
,还简略介绍了 Registry
中的核心组件:Glide 源码阅览笔记(三)
第四篇文章中介绍了 Glide
怎样加载内存缓存和磁盘缓存的资源。其间内存缓存又分为存活的内存缓存资源和被缓存的内存缓存资源;磁盘缓存分为 RESOURCE_CACHE
类型(有尺度等参数作为 key
)缓存与 DATA_CACHE
类型(从网络中加载的原始缓存数据,无尺度等等信息):Glide 源码阅览笔记(四)
本篇文章持续接着上篇文章中介绍没有磁盘缓存和内存缓存时,怎样加载网络中的数据,以及怎样写入 RESOURCE_CACHE
与 DATA_CACHE
磁盘缓存。别的再讲讲加载使命对 Android
中生命周期的呼应。
加载网络数据和写入磁盘缓存
在前面的文章中介绍过加载缓存时会工作在 DiskCacheExecutor
中履行(也便是 ResourceCacheGenerator
和 DataCacheGenerator
),而加载网络数据时会在 ActiveSourceExecutor
中履行(SourceGenerator
)。所以咱们就以 SourceGenerator#startNext()
办法开始剖析:
@Override
public boolean startNext() {
// ...
while (!started && hasNextModelLoader()) {
// 找到一个可用的 DataLoader 中的 LoadData 目标
loadData = helper.getLoadData().get(loadDataListIndex++);
// 然后经过 LoadData 中最终的输出目标的 Class 目标,然后去查找 Decoder 和 Transcoder,他们都被封装在 LoadPath 中。
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
// 找到可以用的 LoadPath 目标。
startNextLoad(loadData);
}
}
return started;
}
我删除了部分本次逻辑不会用到的代码,后面再持续看。这儿首要去查找可以用的 DataLoader
,然后获取到它的 LoadData
目标,然后获取到最终它处理后的目标的 Class
目标。咱们这儿其实便是找到一个网络恳求相关的 DataLoader
,咱们输入的目标是 String
类型的地址,然后它的返回目标便是一个 InputStream
。
然后持续查找可以处理 InputStream
的 Decoder
与 Transcoder
,然后他们被封装在 LoadPath
目标中,然后调用 startNextLoad()
办法:
private void startNextLoad(final LoadData<?> toStart) {
loadData.fetcher.loadData(
helper.getPriority(),
new DataCallback<Object>() {
@Override
public void onDataReady(@Nullable Object data) {
// 回调 LoadData 加载网络数据成功。
if (isCurrentRequest(toStart)) {
onDataReadyInternal(toStart, data);
}
}
@Override
public void onLoadFailed(@NonNull Exception e) {
if (isCurrentRequest(toStart)) {
onLoadFailedInternal(toStart, e);
}
}
});
}
便是一个简略的异步回调,成功后会调用 onDataReadyInternal()
办法,其实这个 data
便是 InputStream
。
@Synthetic
void onDataReadyInternal(LoadData<?> loadData, 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);
}
}
上面的代码分为两种情况,一种是答应 DataCache
,一种是不答应,咱们直接看答应缓存的逻辑(不答应缓存更加简略)。它会把 data
保存在 dataToCache
变量中,然后调用 cb
的 reschedule()
办法,这个 cb
其实便是 DecodeJob
,这个办法它会再次触发 SourceGenerator#startNext()
办法,这个时分咱们就能持续看之前咱们删除掉的那部分代码了:
@Override
public boolean startNext() {
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
try {
// 履行缓存 DataCache 操作。
boolean isDataInCache = cacheData(data);
if (!isDataInCache) {
return true;
}
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Failed to properly rewind or write data to cache", e);
}
}
}
// 缓存成功后会调用 DataCacheGenerator#startNext() 办法
if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
sourceCacheGenerator = null;
// ...
return started;
}
由于回调成功后 dataToCache
变量就不为空了,然后经过 cacheData()
办法来缓存 DataCache
到本地磁盘。假如缓存成功,会创立一个 DataCacheGenerator
(它是和 DecodeJob
中的 DataCacheGenerator
是不同的实例),然后调用其 startNext()
办法,简略来说便是缓存成功后再去从缓存中再去加载一次,然后持续后续的操作。
咱们再来看看 cacheData()
办法的完结:
private boolean cacheData(Object dataToCache) throws IOException {
long startTime = LogTime.getLogTime();
boolean isLoadingFromSourceData = false;
try {
// 用 DataRewinder 来封装对应的 data,使其可以重复的读(也便是让 InputStream 可以重复的读)
DataRewinder<Object> rewinder = helper.getRewinder(dataToCache);
// 重置 data。
Object data = rewinder.rewindAndGet();
// 查找对应的 Encoder
Encoder<Object> encoder = helper.getSourceEncoder(data);
// 构建用于写入文件缓存的 DataCacheWriter 目标。
DataCacheWriter<Object> writer = new DataCacheWriter<>(encoder, data, helper.getOptions());
// 构建用于缓存的 DataCacheKey
DataCacheKey newOriginalKey = new DataCacheKey(loadData.sourceKey, helper.getSignature());
DiskCache diskCache = helper.getDiskCache();
// 写入缓存
diskCache.put(newOriginalKey, writer);
// 写入后,判别是否现已写入成功
if (diskCache.get(newOriginalKey) != null) {
// 写入成功后构建一个 DataCacheGenerator 目标
originalKey = newOriginalKey;
sourceCacheGenerator =
new DataCacheGenerator(Collections.singletonList(loadData.sourceKey), helper, this);
// We were able to write the data to cache.
return true;
} else {
isLoadingFromSourceData = true;
// 假如缓存写入失利,就直接回调 DecodeJob。
cb.onDataFetcherReady(
loadData.sourceKey,
rewinder.rewindAndGet(),
loadData.fetcher,
loadData.fetcher.getDataSource(),
loadData.sourceKey);
}
// We failed to write the data to cache.
return false;
} finally {
if (!isLoadingFromSourceData) {
loadData.fetcher.cleanup();
}
}
}
上面代码的注释我写的很清楚了,就不再赘述了,假如写入本地缓存成功,会创立 DataCacheGenerator
,前面咱们提到会调用它的 startNext()
办法,也便是会触发 DataCacheGenerator
去加载方才写入的缓存,DataCacheGenerator
我在上篇文章中现已介绍过了,不知道的同学翻翻前面的文章。
加载成功后会调用 SourceGenerator#onDataFetcherReady()
办法:
@Override
public void onDataFetcherReady(
Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) {
cb.onDataFetcherReady(sourceKey, data, fetcher, loadData.fetcher.getDataSource(), sourceKey);
}
然后持续回调 DecodeJob#onDataFetcherReady()
办法:
@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;
this.isLoadingFromAlternateCacheKey = sourceKey != decodeHelper.getCacheKeys().get(0);
if (Thread.currentThread() != currentThread) {
reschedule(RunReason.DECODE_DATA);
} else {
GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
try {
decodeFromRetrievedData();
} finally {
GlideTrace.endSection();
}
}
}
上面的办法处理也十分简略将回调的各种数据保存在成员变量中,咱们这儿没有切线程,所以接着调用 decodeFromRetrievedData()
。
private void decodeFromRetrievedData() {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey(
"Retrieved data",
startFetchTime,
"data: "
+ currentData
+ ", cache key: "
+ currentSourceKey
+ ", fetcher: "
+ currentFetcher);
}
Resource<R> resource = null;
try {
// 解码
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
if (resource != null) {
// 解码成功
notifyEncodeAndRelease(resource, currentDataSource, isLoadingFromAlternateCacheKey);
} else {
runGenerators();
}
}
经过调用 decodeFromData()
办法来完结解码,解码成功后调用 notifyEncodeAndRelease()
办法。
private <Data> Resource<R> decodeFromData(
DataFetcher<?> fetcher, Data data, DataSource dataSource) throws GlideException {
try {
if (data == null) {
return null;
}
long startTime = LogTime.getLogTime();
Resource<R> result = decodeFromFetcher(data, dataSource);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Decoded result " + result, startTime);
}
return result;
} finally {
fetcher.cleanup();
}
}
持续调用 decodeFromFetcher()
办法。
private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
throws GlideException {
LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
return runLoadPath(data, dataSource, path);
}
获取到对应的 LoadPath
,然后持续调用 runLoadPath()
办法。
private <Data, ResourceType> Resource<R> runLoadPath(
Data data, DataSource dataSource, LoadPath<Data, ResourceType, R> path)
throws GlideException {
Options options = getOptionsWithHardwareConfig(dataSource);
DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
try {
return path.load(
rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
} finally {
rewinder.cleanup();
}
}
这儿持续调用 LoadPath#load()
来完结解码。这儿其实有两个进程,一个是 Decoder
的解码进程,然后是 Transcoder
将 Decoder
的成果转换成 Target
可以渲染的类型。其间 DecodeCallback
可以阻拦处理 Decoder
返回的成果。
@NonNull
@Override
public Resource<Z> onResourceDecoded(@NonNull Resource<Z> decoded) {
return DecodeJob.this.onResourceDecoded(dataSource, decoded);
}
咱们看到又调用了 DecodeJob#onResourceDecoded()
办法。这个办法里边就要来处理 RESOURCE_DISK_CACHE
了。
@Synthetic
@NonNull
<Z> Resource<Z> onResourceDecoded(DataSource dataSource, @NonNull Resource<Z> decoded) {
@SuppressWarnings("unchecked")
Class<Z> resourceSubClass = (Class<Z>) decoded.get().getClass();
Transformation<Z> appliedTransformation = null;
Resource<Z> transformed = decoded;
if (dataSource != DataSource.RESOURCE_DISK_CACHE) {
// 经过 Transformation 对尺度和 ScaleType 的处理。
appliedTransformation = decodeHelper.getTransformation(resourceSubClass);
transformed = appliedTransformation.transform(glideContext, decoded, width, height);
}
// TODO: Make this the responsibility of the Transformation.
if (!decoded.equals(transformed)) {
decoded.recycle();
}
final EncodeStrategy encodeStrategy;
final ResourceEncoder<Z> encoder;
// 判别是否答应 Resource Encoder
if (decodeHelper.isResourceEncoderAvailable(transformed)) {
// 查找对应的 Encoder
encoder = decodeHelper.getResultEncoder(transformed);
// 获取对应的 EncodeStrategy
encodeStrategy = encoder.getEncodeStrategy(options);
} else {
encoder = null;
encodeStrategy = EncodeStrategy.NONE;
}
Resource<Z> result = transformed;
boolean isFromAlternateCacheKey = !decodeHelper.isSourceKey(currentSourceKey);
// 判别是否答应 Resource Cache.
if (diskCacheStrategy.isResourceCacheable(
isFromAlternateCacheKey, dataSource, encodeStrategy)) {
if (encoder == null) {
throw new Registry.NoResultEncoderAvailableException(transformed.get().getClass());
}
final Key key;
// 根据 EncodeStrategy 来选择不同的缓存 Key
switch (encodeStrategy) {
case SOURCE:
key = new DataCacheKey(currentSourceKey, signature);
break;
case TRANSFORMED:
key =
new ResourceCacheKey(
decodeHelper.getArrayPool(),
currentSourceKey,
signature,
width,
height,
appliedTransformation,
resourceSubClass,
options);
break;
default:
throw new IllegalArgumentException("Unknown strategy: " + encodeStrategy);
}
LockedResource<Z> lockedResult = LockedResource.obtain(transformed);
// 初始化 deferredEncodeManager。
deferredEncodeManager.init(key, encoder, lockedResult);
result = lockedResult;
}
return result;
}
上面有一个点需求留意便是假如数据来源是 RESOURCE_DISK_CACHE
那么就不需求裁剪操作,因为 RESOURCE_DISK_CACHE
缓存中的数据现已做过裁剪操作了。假如需求处理 RESOURCE_DISK_CACHE
那么就会初始化 deferredEncodeManager
。
咱们再来看看解码完结后 notifyEncodeAndRelease()
办法是怎样处理的:
private void notifyEncodeAndRelease(
Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
GlideTrace.beginSection("DecodeJob.notifyEncodeAndRelease");
try {
// ...
try {
if (deferredEncodeManager.hasResourceToEncode()) {
deferredEncodeManager.encode(diskCacheProvider, options);
}
} finally {
if (lockedResource != null) {
lockedResource.unlock();
}
}
// ...
} finally {
GlideTrace.endSection();
}
}
咱们看到它会调用 DeferredEncodeManager#encode()
办法:
void encode(DiskCacheProvider diskCacheProvider, Options options) {
GlideTrace.beginSection("DecodeJob.encode");
try {
diskCacheProvider
.getDiskCache()
.put(key, new DataCacheWriter<>(encoder, toEncode, options));
} finally {
toEncode.unlock();
GlideTrace.endSection();
}
}
也没什么好说的了,直接就写入到磁盘缓存中了。
咱们再看看缓存战略的接口:
// 是否可以写入 DataCache 缓存
public abstract boolean isDataCacheable(DataSource dataSource);
// 是否可以写入 ResourceCache 缓存
public abstract boolean isResourceCacheable(
boolean isFromAlternateCacheKey, DataSource dataSource, EncodeStrategy encodeStrategy);
// 是否可以读取 ResourceCache 缓存
public abstract boolean decodeCachedResource();
// 是否可以读取 DataCache 缓存
public abstract boolean decodeCachedData();
Glide
完结了以下几种:
-
AUTOMATIC
(默许战略)
public static final DiskCacheStrategy AUTOMATIC =
new DiskCacheStrategy() {
@Override
public boolean isDataCacheable(DataSource dataSource) {
return dataSource == DataSource.REMOTE;
}
@Override
public boolean isResourceCacheable(
boolean isFromAlternateCacheKey, DataSource dataSource, EncodeStrategy encodeStrategy) {
return ((isFromAlternateCacheKey && dataSource == DataSource.DATA_DISK_CACHE)
|| dataSource == DataSource.LOCAL)
&& encodeStrategy == EncodeStrategy.TRANSFORMED;
}
@Override
public boolean decodeCachedResource() {
return true;
}
@Override
public boolean decodeCachedData() {
return true;
}
};
ALL
public static final DiskCacheStrategy ALL =
new DiskCacheStrategy() {
@Override
public boolean isDataCacheable(DataSource dataSource) {
return dataSource == DataSource.REMOTE;
}
@Override
public boolean isResourceCacheable(
boolean isFromAlternateCacheKey, DataSource dataSource, EncodeStrategy encodeStrategy) {
return dataSource != DataSource.RESOURCE_DISK_CACHE
&& dataSource != DataSource.MEMORY_CACHE;
}
@Override
public boolean decodeCachedResource() {
return true;
}
@Override
public boolean decodeCachedData() {
return true;
}
};
NONE
public static final DiskCacheStrategy NONE =
new DiskCacheStrategy() {
@Override
public boolean isDataCacheable(DataSource dataSource) {
return false;
}
@Override
public boolean isResourceCacheable(
boolean isFromAlternateCacheKey, DataSource dataSource, EncodeStrategy encodeStrategy) {
return false;
}
@Override
public boolean decodeCachedResource() {
return false;
}
@Override
public boolean decodeCachedData() {
return false;
}
};
DATA
public static final DiskCacheStrategy DATA =
new DiskCacheStrategy() {
@Override
public boolean isDataCacheable(DataSource dataSource) {
return dataSource != DataSource.DATA_DISK_CACHE && dataSource != DataSource.MEMORY_CACHE;
}
@Override
public boolean isResourceCacheable(
boolean isFromAlternateCacheKey, DataSource dataSource, EncodeStrategy encodeStrategy) {
return false;
}
@Override
public boolean decodeCachedResource() {
return false;
}
@Override
public boolean decodeCachedData() {
return true;
}
};
RESOURCE
public static final DiskCacheStrategy RESOURCE =
new DiskCacheStrategy() {
@Override
public boolean isDataCacheable(DataSource dataSource) {
return false;
}
@Override
public boolean isResourceCacheable(
boolean isFromAlternateCacheKey, DataSource dataSource, EncodeStrategy encodeStrategy) {
return dataSource != DataSource.RESOURCE_DISK_CACHE
&& dataSource != DataSource.MEMORY_CACHE;
}
@Override
public boolean decodeCachedResource() {
return true;
}
@Override
public boolean decodeCachedData() {
return false;
}
};
生命周期对 Request 的影响
在第二篇文章中我介绍了 Glide
对 Android
生命周期的处理,Glide
会监听 FramgentActivity
和 Fragment
的 onStart()
,onStop()
和 onDestroy()
三个生命周期。这些生命周期时间会下发至 RequestManager
,然后 RequestManager
再去操控它的 Request
。
onStart()
在 onStart()
生命周期中主要是重新开始 onStop()
生命周期中被暂停的 Request
。咱们直接看看 RequestManager#onStart()
办法源码:
@Override
public synchronized void onStart() {
// 康复暂停的 Request。
resumeRequests();
// 回调 Target 的 onStart() 办法。
targetTracker.onStart();
}
咱们首要看看 resumeRequests()
办法中是怎样暂停 Request
的:
public synchronized void resumeRequests() {
requestTracker.resumeRequests();
}
持续追寻 RequestTracker#resumeRequests()
办法的完结:
public void resumeRequests() {
// 更新暂停状况
isPaused = false;
// 遍历一切的 Request
for (Request request : Util.getSnapshot(requests)) {
// 假如 Request 没有在 Running 状况,调用对应的 begin() 办法
if (!request.isComplete() && !request.isRunning()) {
request.begin();
}
}
// 铲除暂停的 Request 的列表
pendingRequests.clear();
}
上面代码十分简略,遍历一切的暂停的 Request
然后调用其对应的 begin()
办法康复恳求。
咱们再来看看 TargetTracker#onStart()
办法的源码:
@Override
public void onStart() {
for (Target<?> target : Util.getSnapshot(targets)) {
target.onStart();
}
}
朴实无华的代码,遍历一切的 Target
然后调用其 onStart()
办法。
咱们来看看 ImageViewTarget#onStart()
办法是怎样处理的:
@Override
public void onStart() {
if (animatable != null) {
animatable.start();
}
}
其实也便是康复没有履行完结的动画。
onStop()
在 onStop()
生命周期中会暂停没有完结的 Request
,虽然说是暂停,其实并不是真实的暂停,并且网络调用也并不能暂停,Glide
中所谓的暂停,其实便是暂停处理回调成功后的成果,等到下次 onStart()
后再持续处理。咱们持续看看 RequestManager#onStop()
的完结:
@Override
public synchronized void onStop() {
// 调用 Target 的 onStop() 生命周期
targetTracker.onStop();
if (clearOnStop) {
// 铲除没有完结的 Request
clearRequests();
} else {
// 暂停没有完结的 Request
pauseRequests();
}
}
首要经过 TargetTracker#onStop()
办法告诉 Target
的 onStop()
生命周期;后续的代码分为两种情况:经过 pauseRequests()
办法暂停没有完结的 Request
(这也是默许的处理方式);经过 clearRequests()
办法铲除没有完结的 Request
(咱们讲 onDestroy()
的时分再讲这个办法)。
咱们看看 ImageViewTarget#onStop()
怎样处理 onStop()
生命周期的:
@Override
public void onStop() {
if (animatable != null) {
animatable.stop();
}
}
和 onStart()
生命周期对应,便是中止正在履行的动画。
持续看看 pauseRequests()
办法是怎样暂停 Request
的:
public synchronized void pauseRequests() {
requestTracker.pauseRequests();
}
持续追寻 RequestTracker#pauseRequsts()
办法:
public void pauseRequests() {
isPaused = true;
for (Request request : Util.getSnapshot(requests)) {
if (request.isRunning()) {
request.pause();
pendingRequests.add(request);
}
}
}
遍历一切的 Request
,假如正在运转,那么调用 Request#pause()
办法,一起将对应的 Request
增加到 pendingRequests
列表中。
咱们在前面的文章中知道,Request
真实的完结类是 SingleRequest
,咱们来看看 SingleRequest#pause()
是怎样完结的:
@Override
public void pause() {
synchronized (requestLock) {
if (isRunning()) {
clear();
}
}
}
持续调用对应的 clear()
办法:
@Override
public void clear() {
Resource<R> toRelease = null;
synchronized (requestLock) {
assertNotCallingCallbacks();
stateVerifier.throwIfRecycled();
if (status == Status.CLEARED) {
return;
}
cancel();
// Resource must be released before canNotifyStatusChanged is called.
if (resource != null) {
toRelease = resource;
resource = null;
}
if (canNotifyCleared()) {
target.onLoadCleared(getPlaceholderDrawable());
}
GlideTrace.endSectionAsync(TAG, cookie);
status = Status.CLEARED;
}
if (toRelease != null) {
engine.release(toRelease);
}
}
上面代码会持续调用 cancel()
办法,然后将状况更新为 CLEARED
,还或许告诉 Target#onLoadCleared()
办法,这儿的参数用的是 PlaceholderDrawable()
。假如当前的 Resource
不为空,还会将其开释。
咱们来看看 cancel()
办法的完结:
private void cancel() {
assertNotCallingCallbacks();
stateVerifier.throwIfRecycled();
target.removeCallback(this);
if (loadStatus != null) {
loadStatus.cancel();
loadStatus = null;
}
}
首要将 Target
的 Size
回调从 Target
中移除,然后调用 LoadStatus#cancel()
办法。加载 Target
的 Size
在第四篇文章中说过,这个 LoadStatus
是 Engine#load()
办法返回的,用它来操控加载进程中使命,在第四篇文章中也说过。
public void cancel() {
synchronized (Engine.this) {
engineJob.removeCallback(cb);
}
}
其实便是简略将恳求成功/失利的回调从 EngineJob
中移除,或许你忘记了这个 Callback
是什么时分增加进去的,在第四篇文章中讲过,咱们再回想回想 SingleRequest#onSizeReady()
办法:
@Override
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,
callbackExecutor);
// ...
}
}
上面 Engine#load()
办法传递的 this
其实便是上面被移除的 Callback
。所以 Glide
中的暂停其实便是将 SingleRequest
中的 Callback
移除,这会影响后续的 Target
的渲染相关的 UI
流程,可是并不会影响 Engine
中对内存缓存,磁盘缓存的逻辑处理,所以当下次 SingleRequest
康复时,它就可以直接从内存缓存中或者磁盘缓存中快速加载,而不用再恳求网络。
onDestroy()
onDestroy()
也表明 RequestManager
到了生命末期,它和它其间的 Request
与 Target
也都需求被毁掉并且都不可以再康复。
@Override
public synchronized void onDestroy() {
// 对 Target 回调 onDestroy 生命周期
targetTracker.onDestroy();
// 移除 Target 中引用的 Request
clearRequests();
// 铲除一切的 Request
requestTracker.clearRequests();
// 移除 RequestManager 对生命周期的监听
lifecycle.removeListener(this);
// 移除 ConnectiveityMonitor 对生命周期的监听
lifecycle.removeListener(connectivityMonitor);
Util.removeCallbacksOnUiThread(addSelfToLifecycle);
// 告诉 Glide 当前 RquestManager 被移除。
glide.unregisterRequestManager(this);
}
ImageViewTarget
中是把 Request
存放在 ImageView
的 Tag
中,前面有提到过,我这儿再烦琐下。然后咱们再看看 RequestTracker#clearRequests()
办法是怎样铲除 Request
的(留意区别和 pauseRequests()
办法处理的方式):
public void clearRequests() {
for (Request request : Util.getSnapshot(requests)) {
// It's unsafe to recycle the Request here because we don't know who might else have a
// reference to it.
clearAndRemove(request);
}
pendingRequests.clear();
}
遍历一切的 Request
并调用 clearAndRemove()
办法,一起清空 pendingRequests
中暂停的 Request
。
咱们看看 clearAndRemove()
办法的完结:
public boolean clearAndRemove(@Nullable Request request) {
if (request == null) {
// If the Request is null, the request is already cleared and we don't need to search further
// for its owner.
return true;
}
boolean isOwnedByUs = requests.remove(request);
// Avoid short circuiting.
isOwnedByUs = pendingRequests.remove(request) || isOwnedByUs;
if (isOwnedByUs) {
request.clear();
}
return isOwnedByUs;
}
上面会将一切 Request
从 requests
和 pendingRequests
中移除,一起调用 Request#clear()
办法(这个办法咱们上面现已剖析过了),而 resumeRequests()
办法中并不会将 Request
从 reuqests
中移除,并且会将 Request
增加到 pendingRequests
中去,供下次康复时再调用对应的 begin()
办法。
最终
本篇文章介绍了 Glide
怎样加载网络恳求的数据和怎样写入磁盘缓存(包含 ResourceCache
和 DataCache
);还介绍了 RequestManager
具体怎样处理不同的 Android
生命周期。