@Nullable
      @Override
      public Void then(Task<EncodedImage> task) throws Exception {
        if (isTaskCancelled(task)) {
          listener.onProducerFinishWithCancellation(producerContext, PRODUCER_NAME, null);
          consumer.onCancellation();
        } else if (task.isFaulted()) {
          listener.onProducerFinishWithFailure(
              producerContext, PRODUCER_NAME, task.getError(), null);
          startInputProducer(consumer, producerContext, partialImageCacheKey, null);
        } else {
          EncodedImage cachedReference = task.getResult();
          if (cachedReference != null) {
            listener.onProducerFinishWithSuccess(
                producerContext,
                PRODUCER_NAME,
                getExtraMap(listener, producerContext, true, cachedReference.getSize()));
            final BytesRange cachedRange = BytesRange.toMax(cachedReference.getSize() - 1);
            cachedReference.setBytesRange(cachedRange);

            // Create a new ImageRequest for the remaining data
            final int cachedLength = cachedReference.getSize();
            final ImageRequest originalRequest = producerContext.getImageRequest();

            if (cachedRange.contains(originalRequest.getBytesRange())) {
              producerContext.putOriginExtra("disk", "partial");
              listener.onUltimateProducerReached(producerContext, PRODUCER_NAME, true);
              consumer.onNewResult(cachedReference, Consumer.IS_LAST | Consumer.IS_PARTIAL_RESULT);
            } else {
              consumer.onNewResult(cachedReference, Consumer.IS_PARTIAL_RESULT);

              // Pass the request on, but only for the remaining bytes
              final ImageRequest remainingRequest =
                  ImageRequestBuilder.fromRequest(originalRequest)
                      .setBytesRange(BytesRange.from(cachedLength - 1))
                      .build();
              final SettableProducerContext contextForRemainingRequest =
                  new SettableProducerContext(remainingRequest, producerContext);

              startInputProducer(
                  consumer, contextForRemainingRequest, partialImageCacheKey, cachedReference);
            }
          } else {
            listener.onProducerFinishWithSuccess(
                producerContext, PRODUCER_NAME, getExtraMap(listener, producerContext, false, 0));
            startInputProducer(consumer, producerContext, partialImageCacheKey, cachedReference);
          }
        }
        return null;
      }
Partial disk cache producer.

<p>This producer looks in the disk cache to see if it holds part of the requested image. If the
image is found, then it is passed to the consumer as a non-final result, but an adjusted request
is still sent further along to request the remainder of the image.

<p>When the final result comes from the input producer, the two parts are stitched back together
and returned as a whole.
imagepipeline/src/main/java/com/facebook/imagepipeline/producers/PartialDiskCacheProducer.java