前言
DecodeJob的主要工作是從磁盤或者數(shù)據(jù)源(比如網(wǎng)絡(luò))中獲取資源,并進(jìn)行轉(zhuǎn)換和轉(zhuǎn)碼。
class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
Runnable,
Comparable<DecodeJob<?>>,
Poolable {
DecodeJob(DiskCacheProvider diskCacheProvider, Pools.Pool<DecodeJob<?>> pool) {
this.diskCacheProvider = diskCacheProvider;
this.pool = pool;
}
DecodeJob<R> init(
GlideContext glideContext,
Object model,
EngineKey loadKey,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
boolean onlyRetrieveFromCache,
Options options,
Callback<R> callback,
int order) {
decodeHelper.init(
glideContext,
model,
signature,
width,
height,
diskCacheStrategy,
resourceClass,
transcodeClass,
priority,
options,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
diskCacheProvider);
this.glideContext = glideContext;
this.signature = signature;
this.priority = priority;
this.loadKey = loadKey;
this.width = width;
this.height = height;
this.diskCacheStrategy = diskCacheStrategy; //在BaseRequestOptions中默認(rèn)為DiskCacheStrategy.AUTOMATIC
this.onlyRetrieveFromCache = onlyRetrieveFromCache;
this.options = options;
this.callback = callback;
this.order = order;
this.runReason = RunReason.INITIALIZE; //關(guān)注點(diǎn)
this.model = model;
return this;
}
}
DecodeJob 實(shí)現(xiàn)了 Runnable 接口,它運(yùn)行在 EngineJob 里面的線程池里。運(yùn)行時(shí)首先會(huì)檢查是否已經(jīng)取消了執(zhí)行,如果沒有則執(zhí)行 runWrapped()。
在 runWrapped() 中首先會(huì)判斷當(dāng)前的 runReason ,由于在 init() 中被賦值為 INITIALIZE ,則獲取到的 stage 為 Stage.RESOURCE_CACHE ( Stage 表示當(dāng)前執(zhí)行到的階段)。接著根據(jù)當(dāng)前的 Stage 獲取到的 DataFetcherGenerator 為 ResourceCacheGenerator,它用于從磁盤緩存中獲取經(jīng)過轉(zhuǎn)化后的資源。不熟悉這個(gè)類的可以看下 Glide源碼解析之ResourceCacheGenerator
@Override
public void run() {
DataFetcher<?> localFetcher = currentFetcher;
try {
if (isCancelled) {
notifyFailed();
return;
}
runWrapped();
} catch (CallbackException e) {
throw e;
} catch (Throwable t) {
if (stage != Stage.ENCODE) {
throwables.add(t);
notifyFailed();
}
if (!isCancelled) {
throw t;
}
throw t;
} finally {
if (localFetcher != null) {
localFetcher.cleanup();
}
}
}
private void runWrapped() {
runWrappedCount++;
switch (runReason) { //在 init()中賦值為 INITIALIZE
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);
}
}
private Stage getNextStage(Stage current) {
switch (current) {
case INITIALIZE:
return diskCacheStrategy.decodeCachedResource() //默認(rèn)為true
? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
case RESOURCE_CACHE:
return diskCacheStrategy.decodeCachedData() //默認(rèn)為true
? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
case DATA_CACHE:
return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
case SOURCE:
case FINISHED:
return Stage.FINISHED;
default:
throw new IllegalArgumentException("Unrecognized stage: " + current);
}
}
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);
}
}
加載數(shù)據(jù)
獲取到 DataFetcherGenerator 后就開始將獲取數(shù)據(jù)的操作交給它的 startNext() 來執(zhí)行,這里我們以 ResourceCacheGenerator 成功獲取為例,則 isStarted 會(huì)被賦值為 true ,不用進(jìn)入循環(huán)。最終獲取的數(shù)據(jù)會(huì)通過 DecodeJob 實(shí)現(xiàn)的 FetcherReadyCallback 的 onDataFetcherReady() 回調(diào)。
如果 ResourceCacheGenerator 沒有獲取到數(shù)據(jù),由上可知?jiǎng)t依次會(huì)交給 DataCacheGenerator (原數(shù)據(jù)的磁盤緩存) 和 SourceGenerator (從數(shù)據(jù)源加載,比如網(wǎng)絡(luò),不熟悉的可以看下 Glide源碼解析之SourceGenerator)
private void runGenerators() {
boolean isStarted = false;
while (!isCancelled && currentGenerator != null
&& !(isStarted = currentGenerator.startNext())) {
stage = getNextStage(stage);
currentGenerator = getNextGenerator();
if (stage == Stage.SOURCE) {
reschedule();
return;
}
}
if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
notifyFailed();
}
}
加載數(shù)據(jù)完成
在 ResourceCacheGenerator 加載數(shù)據(jù)成功后則通過 onDataFetcherReady() 回調(diào)給 DecodeJob ,由于 ResourceCacheGenerator 并沒有切換線程去獲取資源,所以會(huì)執(zhí)行到 decodeFromRetrievedData() 去進(jìn)行解碼。經(jīng)過一系列的調(diào)用,最終會(huì)將解碼的操作交給 LoadPath 去執(zhí)行。
//ResourceCacheGenerator
@Override
public void onDataReady(Object data) {
cb.onDataFetcherReady(sourceKey, data/*ByteBuffer*/, loadData.fetcher/*ByteBufferFetcher*/, DataSource.RESOURCE_DISK_CACHE,
currentKey);
}
//DecodeJob
@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;
if (Thread.currentThread() != currentThread) {
runReason = RunReason.DECODE_DATA;
callback.reschedule(this);
} else {
try {
decodeFromRetrievedData(); // 執(zhí)行點(diǎn)
} finally {
GlideTrace.endSection();
}
}
}
private void decodeFromRetrievedData() {
Resource<R> resource = null;
try {
resource = decodeFromData(currentFetcher, currentData, currentDataSource); // 執(zhí)行點(diǎn)
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
if (resource != null) {
notifyEncodeAndRelease(resource, currentDataSource);
} else {
runGenerators();
}
}
private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data,
DataSource dataSource) throws GlideException {
try {
if (data == null) {
return null;
}
Resource<R> result = decodeFromFetcher(data, dataSource); // 執(zhí)行點(diǎn)
return result;
} finally {
fetcher.cleanup();
}
}
private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
throws GlideException {
LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass()); // 執(zhí)行點(diǎn)
return runLoadPath(data, dataSource, path);
}
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); // ByteBufferRewinder
try {
return path.load(
rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource)); // 執(zhí)行點(diǎn)
} finally {
rewinder.cleanup();
}
}
開始解碼
會(huì)遍歷 decodePaths 來尋找哪個(gè) DecodePath 是能完成解碼工作的,而具體解碼由分為三步,第一步為解碼資源,第二步為解碼之后的工作(實(shí)際為對(duì)資源進(jìn)行緩存),第三步為轉(zhuǎn)碼,即是將獲取到的資源類型轉(zhuǎn)為另一種資源類型。
//LoadPath
public Resource<Transcode> load(DataRewinder<Data> rewinder, @NonNull Options options, int width,
int height, DecodePath.DecodeCallback<ResourceType> decodeCallback) throws GlideException {
List<Throwable> throwables = Preconditions.checkNotNull(listPool.acquire());
try {
return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables); // 執(zhí)行點(diǎn)
} finally {
listPool.release(throwables);
}
}
private Resource<Transcode> loadWithExceptionList(DataRewinder<Data> rewinder,
@NonNull Options options,
int width, int height, DecodePath.DecodeCallback<ResourceType> decodeCallback,
List<Throwable> exceptions) throws GlideException {
Resource<Transcode> result = null;
for (int i = 0, size = decodePaths.size(); i < size; i++) {
DecodePath<Data, ResourceType, Transcode> path = decodePaths.get(i);
try {
result = path.decode(rewinder, width, height, options, decodeCallback); // 執(zhí)行點(diǎn)
} catch (GlideException e) {
exceptions.add(e);
}
if (result != null) {
break;
}
}
if (result == null) {
throw new GlideException(failureMessage, new ArrayList<>(exceptions));
}
return result;
}
//DecodePath
public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
@NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
return transcoder.transcode(transformed, options);
}
解碼資源
當(dāng)資源類型是 ByteBuffer 的時(shí)候,對(duì)應(yīng)的 DataRewinder 是 ByteBufferRewinder ,ResourceDecoder 是 ByteBufferBitmapDecoder ,則最終的解碼操作將由 ByteBufferBitmapDecoder 來完成。
@NonNull
private Resource<ResourceType> decodeResource(DataRewinder<DataType> rewinder, int width,
int height, @NonNull Options options) throws GlideException {
List<Throwable> exceptions = Preconditions.checkNotNull(listPool.acquire());
try {
return decodeResourceWithList(rewinder, width, height, options, exceptions); //執(zhí)行點(diǎn)
} finally {
listPool.release(exceptions);
}
}
@NonNull
private Resource<ResourceType> decodeResourceWithList(DataRewinder<DataType> rewinder /*ByteBufferRewinder*/, int width,
int height, @NonNull Options options, List<Throwable> exceptions) throws GlideException {
Resource<ResourceType> result = null;
for (int i = 0, size = decoders.size(); i < size; i++) {
ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);
try {
DataType data = rewinder.rewindAndGet();
if (decoder.handles(data, options)) {
//ByteBufferBitmapDecoder
data = rewinder.rewindAndGet();
result = decoder.decode(data, width, height, options); //執(zhí)行點(diǎn)
}
} catch (IOException | RuntimeException | OutOfMemoryError e) {
exceptions.add(e);
}
if (result != null) {
break;
}
}
if (result == null) {
throw new GlideException(failureMessage, new ArrayList<>(exceptions));
}
return result;
}
首先會(huì)將 ByteBuffer 轉(zhuǎn)化為 InputStream ,然后再交給 Downsampler來解碼。
public class ByteBufferBitmapDecoder implements ResourceDecoder<ByteBuffer, Bitmap> {
private final Downsampler downsampler;
public ByteBufferBitmapDecoder(Downsampler downsampler) {
this.downsampler = downsampler;
}
@Override
public boolean handles(@NonNull ByteBuffer source, @NonNull Options options) {
return downsampler.handles(source);
}
@Override
public Resource<Bitmap> decode(@NonNull ByteBuffer source, int width, int height,
@NonNull Options options)
throws IOException {
InputStream is = ByteBufferUtil.toStream(source);
return downsampler.decode(is, width, height, options);
}
}
//Downsampler
public boolean handles(@SuppressWarnings("unused") ByteBuffer byteBuffer) {
return true;
}
//ByteBufferUtil
public static InputStream toStream(@NonNull ByteBuffer buffer) {
return new ByteBufferStream(buffer);
}
在解碼操作里首先會(huì)根據(jù) Bitmap 的寬高和 ImageView 的寬高來計(jì)算出縮放值,然后從 BitmapPool 獲取一個(gè)合適寬高的 Bitmap 交給 BitmapFactory 去進(jìn)行最終的解碼操作,最后再判斷是否需要對(duì) Bitmap 進(jìn)行旋轉(zhuǎn)。
獲取到 Bitmap 后將它包裝進(jìn) BitmapResource 里返回,到此解碼資源的工作就完成了。
//Downsampler
public Resource<Bitmap> decode(InputStream is, int outWidth, int outHeight,
Options options) throws IOException {
return decode(is, outWidth, outHeight, options, EMPTY_CALLBACKS);
}
public Resource<Bitmap> decode(InputStream is, int requestedWidth, int requestedHeight,
Options options, DecodeCallbacks callbacks) throws IOException {
//省略取值代碼
try {
Bitmap result = decodeFromWrappedStreams(is, bitmapFactoryOptions,
downsampleStrategy, decodeFormat, isHardwareConfigAllowed, requestedWidth,
requestedHeight, fixBitmapToRequestedDimensions, callbacks);
return BitmapResource.obtain(result, bitmapPool);
} finally {
releaseOptions(bitmapFactoryOptions);
byteArrayPool.put(bytesForOptions);
}
}
private Bitmap decodeFromWrappedStreams(InputStream is,
BitmapFactory.Options options, DownsampleStrategy downsampleStrategy,
DecodeFormat decodeFormat, boolean isHardwareConfigAllowed, int requestedWidth,
int requestedHeight, boolean fixBitmapToRequestedDimensions,
DecodeCallbacks callbacks) throws IOException {
//省略代碼
//計(jì)算圖片的縮放值,設(shè)置給 options
calculateScaling(
imageType,
is,
callbacks,
bitmapPool,
downsampleStrategy,
degreesToRotate,
sourceWidth,
sourceHeight,
targetWidth,
targetHeight,
options);
//計(jì)算配置
calculateConfig(
is,
decodeFormat,
isHardwareConfigAllowed,
isExifOrientationRequired,
options,
targetWidth,
targetHeight);
boolean isKitKatOrGreater = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
if ((options.inSampleSize == 1 || isKitKatOrGreater) && shouldUsePool(imageType)) {
//不用縮放或者系統(tǒng)版本大于19,而且可以使用 BitmapPool
int expectedWidth;
int expectedHeight;
if (sourceWidth >= 0 && sourceHeight >= 0
&& fixBitmapToRequestedDimensions && isKitKatOrGreater) {
expectedWidth = targetWidth;
expectedHeight = targetHeight;
} else {
float densityMultiplier = isScaling(options)
? (float) options.inTargetDensity / options.inDensity : 1f;
int sampleSize = options.inSampleSize;
int downsampledWidth = (int) Math.ceil(sourceWidth / (float) sampleSize);
int downsampledHeight = (int) Math.ceil(sourceHeight / (float) sampleSize);
expectedWidth = Math.round(downsampledWidth * densityMultiplier);
expectedHeight = Math.round(downsampledHeight * densityMultiplier);
}
if (expectedWidth > 0 && expectedHeight > 0) {
setInBitmap(options, bitmapPool, expectedWidth, expectedHeight); //去 BitmapPool 中獲取期望寬高的 Bitmap (設(shè)置給 options.inBitmap)
}
}
Bitmap downsampled = decodeStream(is, options, callbacks, bitmapPool); //執(zhí)行點(diǎn)
callbacks.onDecodeComplete(bitmapPool, downsampled); //空實(shí)現(xiàn)
Bitmap rotated = null;
if (downsampled != null) {
// 在上面 calculateScaling() 會(huì)修改 inDensity,這里設(shè)置回來
downsampled.setDensity(displayMetrics.densityDpi);
rotated = TransformationUtils.rotateImageExif(bitmapPool, downsampled, orientation); //旋轉(zhuǎn)圖片
if (!downsampled.equals(rotated)) {
//如果旋轉(zhuǎn)了,則緩存旋轉(zhuǎn)后的 Bitmap 。如果沒旋轉(zhuǎn)則還是原來的 Bitmap
bitmapPool.put(downsampled);
}
}
return rotated;
}
private static Bitmap decodeStream(InputStream is, BitmapFactory.Options options,
DecodeCallbacks callbacks, BitmapPool bitmapPool) throws IOException {
if (options.inJustDecodeBounds) {
is.mark(MARK_POSITION);
} else {
callbacks.onObtainBounds();
}
int sourceWidth = options.outWidth;
int sourceHeight = options.outHeight;
String outMimeType = options.outMimeType;
final Bitmap result;
TransformationUtils.getBitmapDrawableLock().lock();
try {
result = BitmapFactory.decodeStream(is, null, options); //最終還是靠 BitmapFactory 來生成 Bitmap 的
} catch (IllegalArgumentException e) {
IOException bitmapAssertionException =
newIoExceptionForInBitmapAssertion(e, sourceWidth, sourceHeight, outMimeType, options);
throw bitmapAssertionException;
} finally {
TransformationUtils.getBitmapDrawableLock().unlock();
}
return result;
}
編碼資源
解碼資源完成后接著就輪到編碼資源了,由 DecodeCallback (接口) 去執(zhí)行,在 DecodeJob 的 runLoadPath() 中給callback 賦的值是 DecodeCallback (實(shí)現(xiàn)類),而它將具體的編碼操作又交回給了 DecodeJob 的 onResourceDecoded()去執(zhí)行。
首先會(huì)判斷資源是否可以編碼,由上可知資源類型為 Bitmap ,是可以編碼的。接著判斷是否可以進(jìn)行緩存,由于這里是從 ResourceCacheGenerator 獲取數(shù)據(jù)的,本來就是從緩存中取得數(shù)據(jù),所以不再需要進(jìn)行緩存,最終會(huì)將源數(shù)據(jù)返回。
如果是需要緩存的則會(huì)交給 DeferredEncodeManager 進(jìn)行磁盤緩存,如果對(duì)磁盤緩存不熟悉的可以看下 Glide源碼解析之DiskCache
//DecodePath
public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
@NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
Resource<ResourceType> transformed = callback.onResourceDecoded(decoded); //執(zhí)行點(diǎn)
return transcoder.transcode(transformed, options);
}
private final class DecodeCallback<Z> implements DecodePath.DecodeCallback<Z> {
private final DataSource dataSource;
@Synthetic
DecodeCallback(DataSource dataSource) {
this.dataSource = dataSource;
}
@NonNull
@Override
public Resource<Z> onResourceDecoded(@NonNull Resource<Z> decoded) {
return DecodeJob.this.onResourceDecoded(dataSource, decoded);
}
}
<Z> Resource<Z> onResourceDecoded(DataSource dataSource,
@NonNull Resource<Z> decoded) {
Class<Z> resourceSubClass = (Class<Z>) decoded.get().getClass();
Transformation<Z> appliedTransformation = null;
Resource<Z> transformed = decoded;
// ResourceCacheGenerator 回調(diào)給 DecodeJob 的就是 DataSource.RESOURCE_DISK_CACHE
if (dataSource != DataSource.RESOURCE_DISK_CACHE) {
appliedTransformation = decodeHelper.getTransformation(resourceSubClass);
transformed = appliedTransformation.transform(glideContext, decoded, width, height);
}
if (!decoded.equals(transformed)) {
decoded.recycle();
}
final EncodeStrategy encodeStrategy;
final ResourceEncoder<Z> encoder;
if (decodeHelper.isResourceEncoderAvailable(transformed)) {
encoder = decodeHelper.getResultEncoder(transformed); // BitmapEncoder
encodeStrategy = encoder.getEncodeStrategy(options); // EncodeStrategy.TRANSFORMED
} else {
encoder = null;
encodeStrategy = EncodeStrategy.NONE;
}
Resource<Z> result = transformed;
//從 ResourceCacheGenerator 獲取數(shù)據(jù)用的是 sourceKey ,所以這里是 false。
//因?yàn)槲覀儽緛砭褪菑木彺嬷腥〉臄?shù)據(jù),所以并不需要再次緩存。
boolean isFromAlternateCacheKey = !decodeHelper.isSourceKey(currentSourceKey);
if (diskCacheStrategy.isResourceCacheable(isFromAlternateCacheKey, dataSource,
encodeStrategy)) {
//這里面是生成緩存的 Key ,并將緩存的操作交給 deferredEncodeManager 去執(zhí)行
if (encoder == null) {
throw new Registry.NoResultEncoderAvailableException(transformed.get().getClass());
}
final Key key;
switch (encodeStrategy) {
case SOURCE:
key = new DataCacheKey(currentSourceKey, signature); //代表緩存的是源數(shù)據(jù)
break;
case TRANSFORMED:
key =
new ResourceCacheKey(
decodeHelper.getArrayPool(),
currentSourceKey,
signature,
width,
height,
appliedTransformation,
resourceSubClass,
options); //代表緩存的是經(jīng)過轉(zhuǎn)化的數(shù)據(jù)
break;
default:
throw new IllegalArgumentException("Unknown strategy: " + encodeStrategy);
}
LockedResource<Z> lockedResult = LockedResource.obtain(transformed);
deferredEncodeManager.init(key, encoder, lockedResult);
result = lockedResult;
}
return result;
}
//DeferredEncodeManager
void encode(DiskCacheProvider diskCacheProvider, Options options) {
try {
//進(jìn)行磁盤緩存
diskCacheProvider.getDiskCache().put(key,
new DataCacheWriter<>(encoder, toEncode, options));
} finally {
toEncode.unlock();
}
}
轉(zhuǎn)碼
將 Resource<Bitmap> 傳進(jìn) LazyBitmapDrawableResource ,而 LazyBitmapDrawableResource 有一個(gè) get() 將 Resource<Bitmap> 轉(zhuǎn)化為 BitmapDrawable 。到此數(shù)據(jù)的獲取過程就結(jié)束了。
//BitmapDrawableTranscoder
public Resource<BitmapDrawable> transcode(@NonNull Resource<Bitmap> toTranscode,
@NonNull Options options) {
return LazyBitmapDrawableResource.obtain(resources, toTranscode);
}
//LazyBitmapDrawableResource
public static Resource<BitmapDrawable> obtain(
@NonNull Resources resources, @Nullable Resource<Bitmap> bitmapResource) {
if (bitmapResource == null) {
return null;
}
return new LazyBitmapDrawableResource(resources, bitmapResource);
}
public BitmapDrawable get() {
return new BitmapDrawable(resources /*這是 Android 里面的 Resource */, bitmapResource.get());
}
處理數(shù)據(jù)
讓我們回到 DecodeJob 一開始獲取數(shù)據(jù)的時(shí)候,在獲取到數(shù)據(jù)之后通過回調(diào)將數(shù)據(jù)傳給 EngineJob 。接著如果需要緩存的則調(diào)用 deferredEncodeManager 去執(zhí)行,最后釋放資源。到此 DecodeJob 的使命就全部完成了。
//DecodeJob
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) {
notifyEncodeAndRelease(resource, currentDataSource); //執(zhí)行點(diǎn)
} else {
runGenerators();
}
}
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
if (resource instanceof Initializable) {
((Initializable) resource).initialize();
}
Resource<R> result = resource;
LockedResource<R> lockedResource = null;
if (deferredEncodeManager.hasResourceToEncode()) {
lockedResource = LockedResource.obtain(resource);
result = lockedResource;
}
notifyComplete(result, dataSource); //執(zhí)行點(diǎn)
stage = Stage.ENCODE;
try {
if (deferredEncodeManager.hasResourceToEncode()) {
//上面說過 deferredEncodeManager 是用來調(diào)用磁盤緩存的,就是在這里調(diào)用
deferredEncodeManager.encode(diskCacheProvider, options);
}
} finally {
if (lockedResource != null) {
lockedResource.unlock();
}
}
//釋放資源
onEncodeComplete();
}
private void notifyComplete(Resource<R> resource, DataSource dataSource) {
callback.onResourceReady(resource, dataSource);
}
//EngineJob
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
synchronized (this) {
this.resource = resource;
this.dataSource = dataSource;
}
notifyCallbacksOfResult();
}