DecodeJob任务
该任务获取图片,可以从资源中,文件缓存,或者网络中获取。下面看一下它的run方法。
public void run() {
TraceCompat.beginSection("DecodeJob#run");
DataFetcher<?> localFetcher = currentFetcher;
try {
if (isCancelled) {
notifyFailed();
return;
}
runWrapped();
} catch (Throwable t) {
if (stage != Stage.ENCODE) {
throwables.add(t);
notifyFailed();
}
if (!isCancelled) {
throw t;
}
} finally {
if (localFetcher != null) {
localFetcher.cleanup();
}
TraceCompat.endSection();
}
}
该任务的run方法,调用内部的核心方法runWrapped。在这个方法中,将决定从哪个地方获取图片。
private void runWrapped() {
switch (runReason) {
case INITIALIZE:
//初始阶段是Stage.INITIALIZE
stage = getNextStage(Stage.INITIALIZE);
currentGenerator = getNextGenerator();
runGenerators();
break;
case SWITCH_TO_SOURCE_SERVICE:
runGenerators();
break;
case DECODE_DATA:
decodeFromRetrievedData();
break;
default:
//异常抛出
}
任务创建时,RunReason初始化INITIALIZE,所以,在第一次执行该任务时,会走INITIALIZE的分支,获取到阶段和生产者,然后运行生产者。
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;
}
}
if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
notifyFailed();
}
}
在while循环中,获取Generator生产者,然后调用它的startNext方法,如果返回标志是false,继续循环获取下一个生产者。
Stage阶段获取,阶段有六个。
private Stage getNextStage(Stage current) {
switch (current) {
case INITIALIZE:
return diskCacheStrategy.decodeCachedResource()
? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
case RESOURCE_CACHE:
return diskCacheStrategy.decodeCachedData()
? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
case DATA_CACHE:
return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
case SOURCE:
case FINISHED:
return Stage.FINISHED;
default:
}
}
Generator生产者,根据当前阶段Stage获取,Stage和Generator的对应关系。
Stage | Generator |
---|---|
RESOURCE_CACHE | ResourceCacheGenerator。 |
DATA_CACHE | DataCacheGenerator。 |
SOURCE | SourceGenerator。 |
三种生产者,SourceGenerator网络请求,DataCacheGenerator从缓存文件获取,ResourceCacheGenerator从资源文件获取。
我们再回到runGenerators方法,我们根据当前阶段,获取到对应Generator,然后执行它的startNext方法,如果失败,继续获取下一个阶段和生产者。
举个例子,我从url中load图片,这时,初始Stage是RESOURCE_CACHE,初始ResourceCacheGenerator,生产者startNext方法返回false,然后,在while循环中获取Stage是DATA_CACHE,对应生产者是DataCacheGenerator,继续startNext方法,磁盘缓存还没有存储,依然返回false。最后获取到SourceGenerator生产者,阶段变成SOURCE。这时,退出while循环,执行reschedule方法,设置该任务RunReason为SWITCH_TO_SOURCE_SERVICE,触发回调Callback的reschedule方法,EngindJob实现了该回调。再次向线程池派发该DecodeJob任务。
当再次运行DecodeJob#runWrapped方法时,RunReason已经变成了SWITCH_TO_SOURCE_SERVICE,直接执行runGenerators方法,当前生产者就是上次已经获取的SourceGenerator,执行它的startNext方法。
@Override
public boolean startNext() {
//当已经有了网络数据时,dataToCache不空,存储磁盘缓存中。
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;
}
当第一次来到此方法时,dataToCache是空,内部生产者DataCacheGenerator也是空。这里会调用ModelLoader.LoadData<?>内部DataFetcher的loadData方法,这里就是发起网路请求的地方。
ResourceCacheGenerator从Disk缓存中根据key获取变换过的资源,这三个Generator都会执行startNext方法,返回false,说明没有找到资源,再通过下一个Generator。
ResourceCacheGenerator中查找File是空,就不会为其创建ModelLoader列表,不会利用LoadData的DataFetcher加载数据。DataFetcher是真正的数据抓取者。
如果是资源文件,使用的是ResourceCacheGenerator生产者。当获取到的File不是空,才会生成ModelLoader列表。
再看一下DataCacheGenerator。根据originalKey获取File,当File存在时,初始化ModelLoader列表,结束循环,如果列表一直是空,会循环多次。同样,由ModelLoader来创建LoadData,利用它的DataFetcher加载数据。
ByteBufferFileLoader实现ModelLoader接口,内部ByteBufferFetcher实现DataFetcher接口,因此,调用的ByteBufferFetcher的loadData方法。结果是ByteBuffer。将该数据交给DecodeJob的onDataFetcherReady方法。
调用decodeFromFetcher方法。
该方法最后找到ByteBufferBitmapDecoder。调用它的decode方法。
当有一个startNext成功,结束掉runGenerators中的while循环。
三个Generator都实现了DataFetcher.DataCallback<Object>接口,用于加载回调,在回调方法中,统一都调用FetcherReadyCallback的回调方法。DecodeJob任务实现FetcherReadyCallback回调。
LoadPath中有一个DecodePath列表,通过调试,里面有三个DecodePath,分别是,在LoadPath的load方法中,找到每一个DecodePath,触发他们的decode方法。
资源通过EngineJob的回调方法,onResourceReady,存储在EngineJob中。然后向主线程发送一个消息,handleResultOnMainThread处理。
回调监听器EngineJobListener的方法,拿到SingleRequest,它实现了ResourceCallback,因此,回调ResourceCallback的方法,这时候已经是主线程在执行了。触发Target的onResourceReady方法,最后通知成功notifyLoadSuccess。
解析Decode是用的StreamBitmapDecoder,他在BitmapDrawableDecoder的内部,在调用BitmapDrawableDecoder的decode方法时,触发StreamBitmapDecoder的decode方法。他们都实现了ResourceDecoder接口。
StreamBitmapDecoder调用Downsampler的decode方法。传入宽高,InputStream流,获取到Bitmap,封装到BitmapResource中。
未完成,待整理
任重而道远
网友评论