fresco请求部分分析
SimpleDraweeView在setImageURI的时候,对controller做了默认设置,虽然是DraweeController,但是其实SimpleDraweeView使用到的真正的Controller类是PipeLineDraweeControllerBuilder:
public void setImageURI(Uri uri, @Nullable Object callerContext) {
DraweeController controller = mSimpleDraweeControllerBuilder
.setCallerContext(callerContext)
.setUri(uri)
.setOldController(getController())
.build();
setController(controller);
}
其中的build()方法便是调用了controller的抽象建造者AbstrateDraweeControllerBuilder类中的build()方法:
public AbstractDraweeController build() {
validate();
// if only a low-res request is specified, treat it as a final request.
if (mImageRequest == null && mMultiImageRequests == null && mLowResImageRequest != null) {
mImageRequest = mLowResImageRequest;
mLowResImageRequest = null;
}
return buildController();
}
protected AbstractDraweeController buildController() {
AbstractDraweeController controller = obtainController();
maybeBuildAndSetRetryManager(controller);
maybeAttachListeners(controller);
return controller;
}
该方法中返回的buildController()会执行到SimpleDraweeView本身使用到的PipeLineDraweeControllerBuilder中的obtainController():
protected PipelineDraweeController obtainController() {
DraweeController oldController = getOldController();
PipelineDraweeController controller;
if (oldController instanceof PipelineDraweeController) {
controller = (PipelineDraweeController) oldController;
controller.initialize(
obtainDataSourceSupplier(),
generateUniqueControllerId(),
getCallerContext());
} else {
controller = mPipelineDraweeControllerFactory.newController(
obtainDataSourceSupplier(),
generateUniqueControllerId(),
getCallerContext());
}
return controller;
}
代码中的obtainDataSourceSupplier()方法便是获取图片数据的方法,此方法又属于其父类AbstrateDraweeControllerBuilder,代码为:
protected Supplier<DataSource<IMAGE>> obtainDataSourceSupplier() {
if (mDataSourceSupplier != null) {
return mDataSourceSupplier;
}
Supplier<DataSource<IMAGE>> supplier = null;
// final image supplier;
if (mImageRequest != null) {
supplier = getDataSourceSupplierForRequest(mImageRequest);
} else if (mMultiImageRequests != null) {
supplier = getFirstAvailableDataSourceSupplier(mMultiImageRequests);
}
// increasing-quality supplier; highest-quality supplier goes first
if (supplier != null && mLowResImageRequest != null) {
List<Supplier<DataSource<IMAGE>>> suppliers = new ArrayList<>(2);
suppliers.add(supplier);
suppliers.add(getDataSourceSupplierForRequest(mLowResImageRequest));
supplier = IncreasingQualityDataSourceSupplier.create(suppliers);
}
// no image requests; use null data source supplier
if (supplier == null) {
supplier = DataSources.getFailedDataSourceSupplier(NO_REQUEST_EXCEPTION);
}
return supplier;
}
其中的重点为getDataSourceSupplierForRequest()方法和getFirstAvailableDataSourceSupplier()方法,其实getFirstAvailableDataSourceSupplier方法进去看一下就能发现,他将对各请求循环遍历了下,但是最终还是调用到了getDataSourceSupplierForRequest()方法。由此可见,一个是针对单个请求的方法,一个是针对请求list的方法。我们下面看一下getDataSourceSupplierForRequest()的代码:
protected Supplier<DataSource<IMAGE>> getDataSourceSupplierForRequest(
final REQUEST imageRequest,
final boolean bitmapCacheOnly) {
final Object callerContext = getCallerContext();
return new Supplier<DataSource<IMAGE>>() {
@Override
public DataSource<IMAGE> get() {
return getDataSourceForRequest(imageRequest, callerContext, bitmapCacheOnly);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("request", imageRequest.toString())
.toString();
}
};
}
此方法中的重点是getDataSourceForRequest()
方法,该方法是抽象方法,即真正调用的时候是使用的子类的方法。即PipeLineDraweeControllerBuilder中的getDataSourceForRequest()方法。进去看一下:
protected DataSource<CloseableReference<CloseableImage>> getDataSourceForRequest(
ImageRequest imageRequest,
Object callerContext,
boolean bitmapCacheOnly) {
if (bitmapCacheOnly) {
return mImagePipeline.fetchImageFromBitmapCache(imageRequest, callerContext);
} else {
return mImagePipeline.fetchDecodedImage(imageRequest, callerContext);
}
}
此处便是重点,请求也有了,接下来就是调用ImagePipeline中的方法去获取图片。其中重要的方法是fetchImageFromBitmapCache()和fetchDecodedImage()个,第一个方法是通过请求去下载图片,第二个方法是从DataSource中找到图片并解码出来。重点看一下第一个方法:
public DataSource<CloseableReference<CloseableImage>> fetchImageFromBitmapCache(
ImageRequest imageRequest,
Object callerContext) {
try {
Producer<CloseableReference<CloseableImage>> producerSequence =
mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest);
return submitFetchRequest(
producerSequence,
imageRequest,
ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE,
callerContext);
} catch (Exception exception) {
return DataSources.immediateFailedDataSource(exception);
}
}
此时调用到了ProducerSequenceFactory的getDecodedImageProducerSequence()方法,
public Producer<CloseableReference<CloseableImage>> getDecodedImageProducerSequence(
ImageRequest imageRequest) {
Producer<CloseableReference<CloseableImage>> pipelineSequence =
getBasicDecodedImageSequence(imageRequest);
if (imageRequest.getPostprocessor() != null) {
return getPostprocessorSequence(pipelineSequence);
} else {
return pipelineSequence;
}
}
重点在getBasicDecodedImageSequence方法中,进去看一下:
private Producer<CloseableReference<CloseableImage>> getBasicDecodedImageSequence(
ImageRequest imageRequest) {
Preconditions.checkNotNull(imageRequest);
Uri uri = imageRequest.getSourceUri();
Preconditions.checkNotNull(uri, "Uri is null.");
if (UriUtil.isNetworkUri(uri)) {
return getNetworkFetchSequence();
} else if (UriUtil.isLocalFileUri(uri)) {
if (MediaUtils.isVideo(MediaUtils.extractMime(uri.getPath()))) {
return getLocalVideoFileFetchSequence();
} else {
return getLocalImageFileFetchSequence();
}
} else if (UriUtil.isLocalContentUri(uri)) {
return getLocalContentUriFetchSequence();
} else if (UriUtil.isLocalAssetUri(uri)) {
return getLocalAssetFetchSequence();
} else if (UriUtil.isLocalResourceUri(uri)) {
return getLocalResourceFetchSequence();
} else if (UriUtil.isDataUri(uri)) {
return getDataFetchSequence();
} else {
String uriString = uri.toString();
if (uriString.length() > 30) {
uriString = uriString.substring(0, 30) + "...";
}
throw new RuntimeException("Unsupported uri scheme! Uri is: " + uriString);
}
}
接下来如果uri正常的话,会执行getNetworkFetchSequence方法:
/**
* swallow result if prefetch -> bitmap cache get ->
* background thread hand-off -> multiplex -> bitmap cache -> decode -> multiplex ->
* encoded cache -> disk cache -> (webp transcode) -> network fetch.
*/
private synchronized Producer<CloseableReference<CloseableImage>> getNetworkFetchSequence() {
if (mNetworkFetchSequence == null) {
mNetworkFetchSequence =
newBitmapCacheGetToDecodeSequence(getCommonNetworkFetchToEncodedMemorySequence());
}
return mNetworkFetchSequence;
}
然后是getCommonNetworkFetchToEncodedMemorySequence()方法,
/**
* multiplex -> encoded cache -> disk cache -> (webp transcode) -> network fetch.
*/
private synchronized Producer<EncodedImage> getCommonNetworkFetchToEncodedMemorySequence() {
if (mCommonNetworkFetchToEncodedMemorySequence == null) {
Producer<EncodedImage> nextProducer =
newEncodedCacheMultiplexToTranscodeSequence(
mProducerFactory.newNetworkFetchProducer(mNetworkFetcher));
mCommonNetworkFetchToEncodedMemorySequence =
ProducerFactory.newAddImageTransformMetaDataProducer(nextProducer);
if (mResizeAndRotateEnabledForNetwork) {
mCommonNetworkFetchToEncodedMemorySequence =
mProducerFactory.newResizeAndRotateProducer(
mCommonNetworkFetchToEncodedMemorySequence);
}
}
return mCommonNetworkFetchToEncodedMemorySequence;
}
此处会使用到ProducerFactory的newNetworkFetchProducer方法:
public NetworkFetchProducer newNetworkFetchProducer(NetworkFetcher networkFetcher) {
return new NetworkFetchProducer(mPooledByteBufferFactory, mByteArrayPool, networkFetcher);
}
返回的结果是NetworkFetchProducer,所有的Producer都会复写父类的produceResults()方法,NetworkFetchProducer则是专门用来处理网络请求的生产者,
@Override
public void produceResults(Consumer<EncodedImage> consumer, ProducerContext context) {
context.getListener()
.onProducerStart(context.getId(), PRODUCER_NAME);
final FetchState fetchState = mNetworkFetcher.createFetchState(consumer, context);
mNetworkFetcher.fetch(
fetchState, new NetworkFetcher.Callback() {
@Override
public void onResponse(InputStream response, int responseLength) throws IOException {
NetworkFetchProducer.this.onResponse(fetchState, response, responseLength);
}
@Override
public void onFailure(Throwable throwable) {
NetworkFetchProducer.this.onFailure(fetchState, throwable);
}
@Override
public void onCancellation() {
NetworkFetchProducer.this.onCancellation(fetchState);
}
});
}
其中最重要的mNetworkFetcher则是之前在ImagePipelineConfig中设置的NetworkFetcher,默认的设置为HttpUrlConnectionNetworkFetcher()类的对象。而真正的请求就发生在该类中:
@Override
public void fetch(final FetchState fetchState, final Callback callback) {
final Future<?> future = mExecutorService.submit(
new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
Uri uri = fetchState.getUri();
String scheme = uri.getScheme();
String uriString = fetchState.getUri().toString();
while (true) {
String nextUriString;
String nextScheme;
InputStream is;
try {
URL url = new URL(uriString);
connection = (HttpURLConnection) url.openConnection();
nextUriString = connection.getHeaderField("Location");
nextScheme = (nextUriString == null) ? null : Uri.parse(nextUriString).getScheme();
if (nextUriString == null || nextScheme.equals(scheme)) {
is = connection.getInputStream();
callback.onResponse(is, -1);
break;
}
uriString = nextUriString;
scheme = nextScheme;
} catch (Exception e) {
callback.onFailure(e);
break;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}
});
fetchState.getContext().addCallbacks(
new BaseProducerContextCallbacks() {
@Override
public void onCancellationRequested() {
if (future.cancel(false)) {
callback.onCancellation();
}
}
});
}
此时生产者的工作基本已经完成,接下来便是回传给消费者的过程。代码中可以看到有一个回调,如果请求成功后会将输入流回传回去,在NetworkFetchProducer中会接收到这个回调并且将输入流转换成输出流。此时则在handleFinalResult方法中,返回数据给消费者。
private void handleFinalResult(
PooledByteBufferOutputStream pooledOutputStream,
FetchState fetchState) {
Map<String, String> extraMap = getExtraMap(fetchState, pooledOutputStream.size());
fetchState.getListener()
.onProducerFinishWithSuccess(fetchState.getId(), PRODUCER_NAME, extraMap);
notifyConsumer(pooledOutputStream, true, fetchState.getConsumer());
}
private void notifyConsumer(
PooledByteBufferOutputStream pooledOutputStream,
boolean isFinal,
Consumer<EncodedImage> consumer) {
CloseableReference<PooledByteBuffer> result =
CloseableReference.of(pooledOutputStream.toByteBuffer());
EncodedImage encodedImage = null;
try {
encodedImage = new EncodedImage(result);
consumer.onNewResult(encodedImage, isFinal);
} finally {
EncodedImage.closeSafely(encodedImage);
CloseableReference.closeSafely(result);
}
}