前言
近期研究了一下Glide的圖片加載框架玷或,在這里和大家分享一下通铲。由于代碼研讀有限毕莱,難免有錯(cuò)誤的地方,了解的童鞋還望指正测暗。學(xué)習(xí)小組QQ群: 193765960央串。
本篇是Glide框架及源碼解析的第四篇,更多文章敬請(qǐng)關(guān)注后續(xù)文章碗啄。如果這篇文章對(duì)大家學(xué)習(xí)Glide有幫助质和,還望大家多多轉(zhuǎn)載。
版權(quán)歸作者所有稚字,如有轉(zhuǎn)發(fā)饲宿,請(qǐng)注明文章出處:http://www.reibang.com/u/d43d948bef39
相關(guān)文章:
跟著源碼學(xué)設(shè)計(jì):Glide框架及源碼解析(一)
跟著源碼學(xué)設(shè)計(jì):Glide框架及源碼解析(二)
跟著源碼學(xué)設(shè)計(jì):Glide框架及源碼解析(三)
跟著源碼學(xué)設(shè)計(jì):Glide框架及源碼解析(四)
跟著源碼學(xué)設(shè)計(jì):Glide框架及源碼解析(五)
在之前的文章中,我們已經(jīng)知道了Glide請(qǐng)求是如何被加載到請(qǐng)求隊(duì)列中并執(zhí)行的胆描,也了解了資源是如何管理的瘫想。本篇文章我們將探究一下資源是如何獲取并分發(fā)的。
資源請(qǐng)求和回調(diào)機(jī)制類(lèi)圖
request開(kāi)啟請(qǐng)求
request被加載到requestTracker中統(tǒng)一管理啟動(dòng)獲取資源昌讲,代碼如下:
public void runRequest(Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
} else {
pendingRequests.add(request);
}
}
- request的執(zhí)行從其begin()方法開(kāi)始:
public void runRequest(Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
} else {
pendingRequests.add(request);
}
}
獲取Engin對(duì)象并封裝任務(wù)
- 獲取engine對(duì)象国夜,在load()方法中創(chuàng)建EnginJob任務(wù)
- 為Enginjob創(chuàng)建異步線程EnginRunnable
- 為EnginRunnable初始化資源獲取解析任務(wù)DecodJob
public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,
Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
Util.assertMainThread();
long startTime = LogTime.getLogTime();
final String id = fetcher.getId();
//獲取key
EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
transcoder, loadProvider.getSourceEncoder());
//查找LruResourceCache
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
cb.onResourceReady(cached);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
//查找ActiveResourceCache
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
//任務(wù)排重
EngineJob current = jobs.get(key);
if (current != null) {
current.addCallback(cb);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
//創(chuàng)建EngineJob
EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);
//創(chuàng)建DecodeJob:注意fetcher(數(shù)據(jù)加載器)
DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,
transcoder, diskCacheProvider, diskCacheStrategy, priority);
//創(chuàng)建任務(wù)線程
EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);
//將任務(wù)加入管理隊(duì)列
jobs.put(key, engineJob);
engineJob.addCallback(cb);
//啟動(dòng)任務(wù)
engineJob.start(runnable);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new LoadStatus(cb, engineJob);
}
執(zhí)行任務(wù)獲取數(shù)據(jù)并解析
- DecodJob通過(guò)數(shù)據(jù)獲取器DataFetcher獲取數(shù)據(jù)文件(流)
request被加載到requestTracker中統(tǒng)一管理啟動(dòng)獲取資源,代碼如下:
//EngineRunnable的run()方法
public void run() {
if (isCancelled) {
return;
}
Exception exception = null;
Resource<?> resource = null;
try {
resource = decode();
} catch (Exception e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Exception decoding", e);
}
exception = e;
}
if (isCancelled) {
if (resource != null) {
resource.recycle();
}
return;
}
if (resource == null) {
onLoadFailed(exception);
} else {
onLoadComplete(resource);
}
}
private Resource<?> decode() throws Exception {
if (isDecodingFromCache()) {
return decodeFromCache();
} else {
return decodeFromSource();
}
}
private Resource<?> decodeFromSource() throws Exception {
return decodeJob.decodeFromSource();
}
- 數(shù)據(jù)解析器對(duì)data數(shù)據(jù)解析生成resource資源對(duì)象
private Resource<T> decodeSource() throws Exception {
Resource<T> decoded = null;
try {
long startTime = LogTime.getLogTime();
//數(shù)據(jù)加載器獲取數(shù)據(jù)
final A data = fetcher.loadData(priority);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Fetched data", startTime);
}
if (isCancelled) {
return null;
}
//data數(shù)據(jù)解析生成resource資源對(duì)象
decoded = decodeFromSourceData(data);
} finally {
fetcher.cleanup();
}
return decoded;
}
//HttpUrlFetcher:網(wǎng)絡(luò)資源加載器
public InputStream loadData(Priority priority) throws Exception {
return loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/, glideUrl.getHeaders());
}
- resource資源進(jìn)一步封裝成為EnginResource對(duì)象
//Runnable的方法短绸,在run()方法中調(diào)用
private void onLoadComplete(Resource resource) {
manager.onResourceReady(resource);
}
//manager.onResourceReady(resource)實(shí)際回調(diào)了Enginjob的接口實(shí)現(xiàn)
public void onResourceReady(final Resource<?> resource) {
this.resource = resource;
MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
}
- 通過(guò)監(jiān)聽(tīng)接口回傳EnginResource對(duì)象
private void handleResultOnMainThread() {
if (isCancelled) {
resource.recycle();
return;
} else if (cbs.isEmpty()) {
throw new IllegalStateException("Received a resource without any callbacks to notify");
}
engineResource = engineResourceFactory.build(resource, isCacheable);
hasResource = true;
// Hold on to resource for duration of request so we don't recycle it in the middle of notifying if it
// synchronously released by one of the callbacks.
engineResource.acquire();
listener.onEngineJobComplete(key, engineResource);
for (ResourceCallback cb : cbs) {
if (!isInIgnoredCallbacks(cb)) {
engineResource.acquire();
//回傳engineResource到request中车吹,request獲取到資源后開(kāi)始刷新UI
cb.onResourceReady(engineResource);
}
}
// Our request is complete, so we can release the resource.
engineResource.release();
}
(本篇是Glide框架及源碼解析的第四篇,更多文章敬請(qǐng)關(guān)注后續(xù)文章醋闭。版權(quán)歸作者所有窄驹,如有轉(zhuǎn)發(fā),請(qǐng)注明文章出處:原文鏈接)