上一節(jié)我們說(shuō)到了如何獲取磁盤緩存和開(kāi)啟圖片請(qǐng)求的,需要回顧的同學(xué)可以繼續(xù)查看:
Glide4.9圖片框架源碼(四)之獲取磁盤緩存和圖片請(qǐng)求
HttpUrlFetcher loadData()
@Override
public void loadData(@NonNull Priority priority,
@NonNull DataCallback<? super InputStream> callback) {
long startTime = LogTime.getLogTime();
try {
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
callback.onDataReady(result);
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Failed to load data for url", e);
}
callback.onLoadFailed(e);
} finally {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));
}
}
}
上一節(jié)我們講述了HttpUrlFetcher調(diào)用loadData請(qǐng)求圖片數(shù)據(jù)并且返回圖片對(duì)應(yīng)的InputStream蜈抓,那么這一節(jié)我們著重看下是如何將InputStream回調(diào)到最初的ViewTarget并且顯示的启绰,所以這里我們要看仔細(xì)每一個(gè)回調(diào)監(jiān)聽(tīng)。這里我們看到調(diào)用了callback.onDataReady(result)方法沟使,那么callback是由loaddata傳進(jìn)來(lái)的委可,我們返回再看看是怎么入?yún)⒌?
SourceGenerator
@Override
public boolean startNext() {
.........
.........
while (!started && hasNextModelLoader()) {
loadData = helper.getLoadData().get(loadDataListIndex++);
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
可以看到SourceGenerator傳入的是this,所以上面的onDataReady方法回調(diào)到SourceGenerator的onDataReady方法腊嗡,我們繼續(xù)看回調(diào):
@Override
public void onDataReady(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);
}
}
這里isDataCacheable是去判讀是否能緩存到磁盤着倾,如果不能,就繼續(xù)往上回調(diào)燕少,如果可以緩存卡者,那么將當(dāng)前的inputstream賦值給dataToCache,然后調(diào)用cb.reschedule()客们,我們來(lái)看看這個(gè)cb監(jiān)聽(tīng)是什么時(shí)候傳進(jìn)來(lái)的:
private final FetcherReadyCallback cb;
private int loadDataListIndex;
private DataCacheGenerator sourceCacheGenerator;
private Object dataToCache;
private volatile ModelLoader.LoadData<?> loadData;
private DataCacheKey originalKey;
SourceGenerator(DecodeHelper<?> helper, FetcherReadyCallback cb) {
this.helper = helper;
this.cb = cb;
}
可以看到FetcherReadyCallback是在SourceGenerator初始化的時(shí)候傳進(jìn)來(lái)的崇决,那么看下SourceGenerator的初始化方法:
DecodeJob
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);
}
}
可以看到是在DecodeJob的getNextGenerator方法中去初始化的,所以我們看看他的reschedule方法:
@Override
public void reschedule() {
runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
callback.reschedule(this);
}
@Override
public void reschedule(DecodeJob<?> job) {
getActiveSourceExecutor().execute(job);
}
可以看到還是重新執(zhí)行了DecodeJob線程镶摘,直接去加載SourceGenerator嗽桩,我們跟進(jìn)去看一下源碼:
@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;
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
private void cacheData(Object dataToCache) {
long startTime = LogTime.getLogTime();
try {
Encoder<Object> encoder = helper.getSourceEncoder(dataToCache);
DataCacheWriter<Object> writer =
new DataCacheWriter<>(encoder, dataToCache, helper.getOptions());
originalKey = new DataCacheKey(loadData.sourceKey, helper.getSignature());
helper.getDiskCache().put(originalKey, writer);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Finished encoding source to cache"
+ ", key: " + originalKey
+ ", data: " + dataToCache
+ ", encoder: " + encoder
+ ", duration: " + LogTime.getElapsedMillis(startTime));
}
} finally {
loadData.fetcher.cleanup();
}
sourceCacheGenerator =
new DataCacheGenerator(Collections.singletonList(loadData.sourceKey), helper, this);
}
由于我們之前已經(jīng)分析過(guò)這一塊的startNext方法,所以這里調(diào)用的是SourceGenerator的startNext凄敢,可以看到第一行直接判讀按dataToCache非空碌冶,dataToCache在剛才獲取input stream的時(shí)候已經(jīng)賦值給dataToCache,所以這里直接執(zhí)行cacheData方法去緩存數(shù)據(jù)涝缝。cacheData里面的helper.getSourceEncoder是通過(guò)傳入的data類型扑庞,返回一個(gè)Encoder對(duì)應(yīng)的解碼器。然后又生成了一個(gè)DataCacheWriter包裝類拒逮,傳入了解碼器和dataToCache流數(shù)據(jù)罐氨,調(diào)用 helper.getDiskCache().put方法,我們跟進(jìn)去看下put方法:
@Override
public void put(Key key, Writer writer) {
String safeKey = safeKeyGenerator.getSafeKey(key);
writeLocker.acquire(safeKey);
try {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Put: Obtained: " + safeKey + " for for Key: " + key);
}
try {
DiskLruCache diskCache = getDiskCache();
Value current = diskCache.get(safeKey);
if (current != null) {
return;
}
DiskLruCache.Editor editor = diskCache.edit(safeKey);
if (editor == null) {
throw new IllegalStateException("Had two simultaneous puts for: " + safeKey);
}
try {
File file = editor.getFile(0);
if (writer.write(file)) {
editor.commit();
}
} finally {
editor.abortUnlessCommitted();
}
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Unable to put to disk cache", e);
}
}
} finally {
writeLocker.release(safeKey);
}
}
可以看到傳進(jìn)來(lái)的writer調(diào)用了write(file)滩援,這里我們就不跟進(jìn)去了栅隐,就是一般的讀取流然后存儲(chǔ)到文件,這里就把數(shù)據(jù)緩存到了硬盤緩存玩徊,回到哦最初的cacheData方法租悄,重新去new DataCacheGenerator并且傳入的監(jiān)聽(tīng)是this,sourceCacheGenerator = new DataCacheGenerator(Collections.singletonList(loadData.sourceKey), helper, this)恩袱,然后繼續(xù)調(diào)用startStage中的sourceCacheGenerator.startNext泣棋,則去調(diào)用了DataCacheGenerator的startNext方法,繼續(xù)看:
@Override
public boolean startNext() {
while (modelLoaders == null || !hasNextModelLoader()) {
sourceIdIndex++;
if (sourceIdIndex >= cacheKeys.size()) {
return false;
}
Key sourceId = cacheKeys.get(sourceIdIndex);
@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;
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
這里為什么又去執(zhí)行一次呢畔塔,其實(shí)這里是從磁盤緩存中去讀取剛剛我們緩存的數(shù)據(jù)潭辈,那么這里的loadData.fetcher.loadData則去緩存中加載緩存圖片文件并且再去回調(diào)鸯屿,我們看下FileFetcher的loadData方法:
@Override
public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super Data> callback) {
try {
data = opener.open(file);
} catch (FileNotFoundException e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Failed to open file", e);
}
callback.onLoadFailed(e);
return;
}
callback.onDataReady(data);
}
直接通過(guò)opener.open去獲取文件,加載的回調(diào)就在DataCacheGenerator的onDataReady中
@Override
public void onDataReady(Object data) {
cb.onDataFetcherReady(sourceKey, data, loadData.fetcher, DataSource.DATA_DISK_CACHE, sourceKey);
}
@Override
public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,
DataSource dataSource, Key attemptedKey) {
cb.onDataFetcherReady(sourceKey, data, fetcher, loadData.fetcher.getDataSource(), sourceKey);
}
@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 {
GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
try {
decodeFromRetrievedData();
} finally {
GlideTrace.endSection();
}
}
}
繼續(xù)回調(diào)依然是到上層的sourceCacheGenerator的onDataFetcherReady中把敢,然后sourceCacheGenerator回調(diào)到Decode中的onDataFetcherReady方法寄摆,這里的currentThread從開(kāi)啟子線程執(zhí)行DecodeJobs后沒(méi)有做過(guò)線程切換,所以依然是當(dāng)前線程技竟,所以執(zhí)行callback.reschedule(this)方法并且賦值runReason為DECODE_DATA準(zhǔn)備再次執(zhí)行Decode線程去解析磁盤緩存回調(diào)的數(shù)據(jù):
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);
}
}
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);
} else {
runGenerators();
}
}
由于是 runReason = RunReason.DECODE_DATA冰肴,所以直接執(zhí)行decodeFromRetrievedData屈藐,這里調(diào)用了decodeFromData去解析數(shù)據(jù)榔组,并返回一個(gè)Resource,這里的Resource就是加載和解析過(guò)后的數(shù)據(jù)联逻,不去細(xì)究搓扯,直接看回調(diào)notifyEncodeAndRelease方法:
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);
stage = Stage.ENCODE;
try {
if (deferredEncodeManager.hasResourceToEncode()) {
deferredEncodeManager.encode(diskCacheProvider, options);
}
} finally {
if (lockedResource != null) {
lockedResource.unlock();
}
}
onEncodeComplete();
}
private void notifyComplete(Resource<R> resource, DataSource dataSource) {
setNotifiedOrThrow();
callback.onResourceReady(resource, dataSource);
}
這里直接看回調(diào)notifyComplete方法,調(diào)用了callback.onResourceReady方法包归,可能我們已經(jīng)忘了這里的callback到底是什么時(shí)候傳進(jìn)來(lái)的锨推,來(lái)看一下:
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) {
......
this.callback = callback;
this.order = order;
this.runReason = RunReason.INITIALIZE;
this.model = model;
return this;
}
可以看到調(diào)用的是DecodeJob的initial方法擎浴,最終發(fā)現(xiàn)這里的callback其實(shí)就是EngineJob本身换薄,所以看一看EngineJob的onResourceReady方法:
@Override
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
synchronized (this) {
this.resource = resource;
this.dataSource = dataSource;
}
notifyCallbacksOfResult();
}
這里分別賦值了resource和dataSource,這兩個(gè)變量就是我們說(shuō)到的磁盤緩存的兩種類型奠旺,繼續(xù)看notifyCallbacksOfResult方法:
void notifyCallbacksOfResult() {
ResourceCallbacksAndExecutors copy;
Key localKey;
EngineResource<?> localResource;
synchronized (this) {
stateVerifier.throwIfRecycled();
if (isCancelled) {
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");
}
engineResource = engineResourceFactory.build(resource, isCacheable);
hasResource = true;
copy = cbs.copy();
incrementPendingCallbacks(copy.size() + 1);
localKey = key;
localResource = engineResource;
}
listener.onEngineJobComplete(this, localKey, localResource);
for (final ResourceCallbackAndExecutor entry : copy) {
entry.executor.execute(new CallResourceReady(entry.cb));
}
decrementPendingCallbacks();
}
@Override
public synchronized void onEngineJobComplete(
EngineJob<?> engineJob, Key key, EngineResource<?> resource) {
// A null resource indicates that the load failed, usually due to an exception.
if (resource != null && resource.isMemoryCacheable()) {
activeResources.activate(key, resource);
}
jobs.removeIfCurrent(key, engineJob);
}
synchronized void activate(Key key, EngineResource<?> resource) {
ResourceWeakReference toPut =
new ResourceWeakReference(
key, resource, resourceReferenceQueue, isActiveResourceRetentionAllowed);
ResourceWeakReference removed = activeEngineResources.put(key, toPut);
if (removed != null) {
removed.reset();
}
}
ResourceCallbacksAndExecutors 這里存儲(chǔ)的是回調(diào)的線程池執(zhí)行器厦幅,我們先看后面沾鳄,有一個(gè)EngineResource對(duì)象,還記得之前我們的內(nèi)存緩存嗎确憨,對(duì)了译荞,這里就是新建一個(gè)緩存對(duì)象,下面的engineResourceFactory.build方法休弃,就是通過(guò)傳入已經(jīng)加載完成的resource生成EngineResource內(nèi)存緩存吞歼。繼續(xù)看listener的onEngineJobComplete方法,傳入了key和engineResource塔猾,這里我們看到了兩個(gè)熟悉的變量篙骡,isMemoryCacheable和activeResources,就是判斷是否緩存到內(nèi)存丈甸,如果是糯俗,那么直接通過(guò)activeResources的activate方法構(gòu)造出ResourceWeakReference并且存儲(chǔ)到弱引用緩存。
回到上面的notifyCallbacksOfResult老虫,存儲(chǔ)到內(nèi)存緩存后叶骨,應(yīng)該開(kāi)始回調(diào)到最初的加載的地方并且設(shè)置圖片了,我們繼續(xù)看下entry.executor.execute(new CallResourceReady(entry.cb))方法祈匙,首先entry里存儲(chǔ)的就是copy的ResourceCallbackAndExecutor忽刽,而copy是通過(guò)調(diào)用cbs的copy方法獲取的天揖,我們跟進(jìn)去看一下
static final class ResourceCallbacksAndExecutors
implements Iterable<ResourceCallbackAndExecutor> {
private final List<ResourceCallbackAndExecutor> callbacksAndExecutors;
ResourceCallbacksAndExecutors() {
this(new ArrayList<ResourceCallbackAndExecutor>(2));
}
void add(ResourceCallback cb, Executor executor) {
callbacksAndExecutors.add(new ResourceCallbackAndExecutor(cb, executor));
}
void remove(ResourceCallback cb) {
callbacksAndExecutors.remove(defaultCallbackAndExecutor(cb));
}
ResourceCallbacksAndExecutors copy() {
return new ResourceCallbacksAndExecutors(new ArrayList<>(callbacksAndExecutors));
}
發(fā)現(xiàn)callbacksAndExecutors就是ResourceCallbacksAndExecutors的一個(gè)變量,通過(guò)調(diào)用add方法添加Executor跪帝,那么我們就跟進(jìn)去看在什么時(shí)候添加了這個(gè)回調(diào)執(zhí)行器今膊。
synchronized void addCallback(final ResourceCallback cb, Executor callbackExecutor) {
stateVerifier.throwIfRecycled();
cbs.add(cb, callbackExecutor);
if (hasResource) {
incrementPendingCallbacks(1);
callbackExecutor.execute(new CallResourceReady(cb));
} else if (hasLoadFailed) {
incrementPendingCallbacks(1);
callbackExecutor.execute(new CallLoadFailed(cb));
} else {
Preconditions.checkArgument(!isCancelled, "Cannot add callbacks to a cancelled EngineJob");
}
}
jobs.put(key, engineJob);
engineJob.addCallback(cb, callbackExecutor);
engineJob.start(decodeJob);
我們發(fā)現(xiàn),callbackExecutor回調(diào)執(zhí)行器在請(qǐng)求圖片資源伞剑,開(kāi)啟decodeJob的時(shí)候就添加進(jìn)來(lái)了斑唬,繼續(xù)往上跟,看清楚callbackExecutor的真正對(duì)象是什么:
<Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
Executor callbackExecutor) {
return into(target, targetListener, /*options=*/ this, callbackExecutor);
}
public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {
return into(target, /*targetListener=*/ null, Executors.mainThreadExecutor());
}
private static final Executor MAIN_THREAD_EXECUTOR =
new Executor() {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(@NonNull Runnable command) {
handler.post(command);
}
};
跟到最初始的地方我們發(fā)現(xiàn)黎泣,原來(lái)在調(diào)用into方法的時(shí)候就已經(jīng)傳入了一個(gè)主線程的執(zhí)行器恕刘,所以回到我們存儲(chǔ)內(nèi)存緩存即將回調(diào)的地方:
for (final ResourceCallbackAndExecutor entry : copy) {
entry.executor.execute(new CallResourceReady(entry.cb));
}
public void run() {
synchronized (cb.getLock()) {
synchronized (EngineJob.this) {
if (cbs.contains(cb)) {
engineResource.acquire();
callCallbackOnResourceReady(cb);
removeCallback(cb);
}
decrementPendingCallbacks();
}
}
}
void callCallbackOnResourceReady(ResourceCallback cb) {
try {
cb.onResourceReady(engineResource, dataSource);
} catch (Throwable t) {
throw new CallbackException(t);
}
}
所以這里的executor,必定存在主線程的MAIN_THREAD_EXECUTOR抒倚,所以在這里實(shí)現(xiàn)了線程切換褐着,將數(shù)據(jù)回調(diào)到了主線程,我們直接看CallResourceReady的run方法托呕,engineResource.acquire()開(kāi)啟了引用計(jì)數(shù)含蓉,表示當(dāng)前內(nèi)存緩存已經(jīng)引用了,繼續(xù)調(diào)用callCallbackOnResourceReady方法项郊,這里的cb.onResourceReady方法就回調(diào)到了singleRequest中馅扣,我們跟進(jìn)去看:
public void onResourceReady(Resource<?> resource, DataSource dataSource) {
stateVerifier.throwIfRecycled();
Resource<?> toRelease = null;
try {
synchronized (requestLock) {
loadStatus = null;
......
......
if (!canSetResource()) {
toRelease = resource;
this.resource = null;
status = Status.COMPLETE;
return;
}
onResourceReady((Resource<R>) resource, (R) received, dataSource);
}
} finally {
if (toRelease != null) {
engine.release(toRelease);
}
}
}
private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
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.onResourceReady(result, model, target, dataSource, isFirstResource);
if (!anyListenerHandledUpdatingTarget) {
Transition<? super R> animation = animationFactory.build(dataSource, isFirstResource);
target.onResourceReady(result, animation);
}
} finally {
isCallingCallbacks = false;
}
notifyLoadSuccess();
}
onResourceReady省略的地方做了一些判斷和失敗的回調(diào),可以忽略着降,我們直接看下面的onResourceReady方法差油,requestListeners和targetListener是最初我們自己是否添加過(guò)加載監(jiān)聽(tīng),如果設(shè)置過(guò)監(jiān)聽(tīng)鹊碍,這里就會(huì)回調(diào)厌殉,我們沒(méi)有設(shè)置直接看target.onResourceReady方法,還記得我們的imageview設(shè)置到哪里了么侈咕,就是target中公罕,因此這里就將數(shù)據(jù)源回調(diào)到了image view中,因此這里調(diào)用imageviewtarget的onResourceReady方法:
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
if (transition == null || !transition.transition(resource, this)) {
setResourceInternal(resource);
} else {
maybeUpdateAnimatable(resource);
}
}
private void setResourceInternal(@Nullable Z resource) {
// non-null Callback before starting it.
setResource(resource);
maybeUpdateAnimatable(resource);
}
DrawableImageViewTarget
protected void setResource(@Nullable Drawable resource) {
view.setImageDrawable(resource);
}
這里的setResource方法也就調(diào)用了DrawableImageViewTarget的setResource方法耀销,可以看到又調(diào)用了view的setImageDrawable方法楼眷,將圖片設(shè)置到view上了,到這里從加載數(shù)據(jù)結(jié)束到存儲(chǔ)到緩存并加載到view上的流程就分析結(jié)束了熊尉。
總結(jié)
HttpUrlFetcher 請(qǐng)求玩圖片后返回給SourceGenerator圖片的input stream罐柳,然后重新執(zhí)行DecodeJob,調(diào)用SourceGenerator的startNext的cacheData方法去緩存數(shù)據(jù)到磁盤然后調(diào)用DataCacheGenerator的startNext方法又去磁盤緩存中加載數(shù)據(jù)狰住,加載完成后再次執(zhí)行DecodeJob方法张吉,去decode解析磁盤緩存得到resource對(duì)象,完成后回調(diào)到EngineJob中催植,然后將resource存儲(chǔ)到弱引用內(nèi)存緩存中肮蛹,引用計(jì)數(shù)加一勺择,調(diào)用主線程的handler將數(shù)據(jù)回調(diào)到主線程的Target中加載并顯示圖片。執(zhí)行流程就是SourceGenerator-->DataCacheGenerator-->DecodeJob-->EngineJob-->SingleRequest-->Target伦忠。到這里整個(gè)圖片的加載流程就分析結(jié)束了省核,下一節(jié)我們?cè)僦v講面試中Glide源碼可能關(guān)注的一些問(wèn)題~