Android图片加载框架Fresco分析(五)

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);
}
  }