Skip to content

Commit

Permalink
Producers themselves are responsible for stopping at lowest level
Browse files Browse the repository at this point in the history
  • Loading branch information
IanChilds authored and tyronen committed Apr 6, 2015
1 parent e1f7ad8 commit 2adb237
Show file tree
Hide file tree
Showing 12 changed files with 117 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,12 @@ public DataSource<CloseableReference<CloseableImage>> fetchImageFromBitmapCache(
ImageRequest imageRequest,
Object callerContext) {
Producer<CloseableReference<CloseableImage>> producerSequence =
mProducerSequenceFactory.getBitmapCacheGetOnlySequence();
return submitFetchRequest(producerSequence, imageRequest, callerContext);
mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest);
return submitFetchRequest(
producerSequence,
imageRequest,
ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE,
callerContext);
}

/**
Expand All @@ -135,9 +139,12 @@ public DataSource<CloseableReference<CloseableImage>> fetchDecodedImage(
ImageRequest imageRequest,
Object callerContext) {
Producer<CloseableReference<CloseableImage>> producerSequence =
mProducerSequenceFactory.getDecodedImageProducerSequence(
imageRequest);
return submitFetchRequest(producerSequence, imageRequest, callerContext);
mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest);
return submitFetchRequest(
producerSequence,
imageRequest,
ImageRequest.RequestLevel.FULL_FETCH,
callerContext);
}

/**
Expand All @@ -152,9 +159,12 @@ public DataSource<CloseableReference<PooledByteBuffer>> fetchEncodedImage(
ImageRequest imageRequest,
Object callerContext) {
Producer<CloseableReference<PooledByteBuffer>> producerSequence =
mProducerSequenceFactory.getEncodedImageProducerSequence(
imageRequest);
return submitFetchRequest(producerSequence, imageRequest, callerContext);
mProducerSequenceFactory.getEncodedImageProducerSequence(imageRequest);
return submitFetchRequest(
producerSequence,
imageRequest,
ImageRequest.RequestLevel.FULL_FETCH,
callerContext);
}

/**
Expand All @@ -170,9 +180,12 @@ public DataSource<Void> prefetchToBitmapCache(
}

Producer<Void> producerSequence =
mProducerSequenceFactory.getDecodedImagePrefetchProducerSequence(
imageRequest);
return submitPrefetchRequest(producerSequence, imageRequest, callerContext);
mProducerSequenceFactory.getDecodedImagePrefetchProducerSequence(imageRequest);
return submitPrefetchRequest(
producerSequence,
imageRequest,
ImageRequest.RequestLevel.FULL_FETCH,
callerContext);
}

/**
Expand All @@ -188,9 +201,12 @@ public DataSource<Void> prefetchToDiskCache(
}

Producer<Void> producerSequence =
mProducerSequenceFactory.getEncodedImagePrefetchProducerSequence(
imageRequest);
return submitPrefetchRequest(producerSequence, imageRequest, callerContext);
mProducerSequenceFactory.getEncodedImagePrefetchProducerSequence(imageRequest);
return submitPrefetchRequest(
producerSequence,
imageRequest,
ImageRequest.RequestLevel.FULL_FETCH,
callerContext);
}

/**
Expand Down Expand Up @@ -221,12 +237,18 @@ public boolean apply(CacheKey key) {
private <T> DataSource<CloseableReference<T>> submitFetchRequest(
Producer<CloseableReference<T>> producerSequence,
ImageRequest imageRequest,
ImageRequest.RequestLevel lowestPermittedRequestLevelOnSubmit,
Object callerContext) {
ImageRequest.RequestLevel lowestPermittedRequestLevel =
ImageRequest.RequestLevel.getMax(
imageRequest.getLowestPermittedRequestLevel(),
lowestPermittedRequestLevelOnSubmit);
SettableProducerContext settableProducerContext = new SettableProducerContext(
imageRequest,
generateUniqueFutureId(),
mRequestListener,
callerContext,
lowestPermittedRequestLevel,
/* isPrefetch */ false,
imageRequest.getProgressiveRenderingEnabled() ||
!UriUtil.isNetworkUri(imageRequest.getSourceUri()),
Expand All @@ -240,12 +262,18 @@ private <T> DataSource<CloseableReference<T>> submitFetchRequest(
private DataSource<Void> submitPrefetchRequest(
Producer<Void> producerSequence,
ImageRequest imageRequest,
ImageRequest.RequestLevel lowestPermittedRequestLevelOnSubmit,
Object callerContext) {
ImageRequest.RequestLevel lowestPermittedRequestLevel =
ImageRequest.RequestLevel.getMax(
imageRequest.getLowestPermittedRequestLevel(),
lowestPermittedRequestLevelOnSubmit);
SettableProducerContext settableProducerContext = new SettableProducerContext(
imageRequest,
generateUniqueFutureId(),
mRequestListener,
callerContext,
lowestPermittedRequestLevel,
/* isPrefetch */ true,
/* isIntermediateResultExpected */ false,
Priority.LOW);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ public class ProducerSequenceFactory {
private final boolean mResizeAndRotateEnabledForNetwork;

// Saved sequences
@VisibleForTesting Producer<CloseableReference<CloseableImage>> mBitmapCacheGetOnlySequence;
@VisibleForTesting Producer<CloseableReference<CloseableImage>> mNetworkFetchSequence;
@VisibleForTesting Producer<CloseableReference<PooledByteBuffer>>
mBackgroundNetworkFetchToEncodedMemorySequence;
Expand Down Expand Up @@ -117,21 +116,6 @@ private static void validateEncodedImageRequest(ImageRequest imageRequest) {
ImageRequest.RequestLevel.FULL_FETCH);
}

/**
* Returns a sequence that can be used for a request that just requires a bitmap cache lookup.
*
* <p> Sequence is: bitmap cache get -> null producer
* @return the sequence that should be used to process the request.
*/
public synchronized Producer<CloseableReference<CloseableImage>> getBitmapCacheGetOnlySequence() {
if (mBitmapCacheGetOnlySequence == null) {
mBitmapCacheGetOnlySequence =
mProducerFactory.newBitmapMemoryCacheGetProducer(
mProducerFactory.<CloseableReference<CloseableImage>>newNullProducer());
}
return mBitmapCacheGetOnlySequence;
}

/**
* Returns a sequence that can be used for a request for a decoded image.
*
Expand Down Expand Up @@ -163,18 +147,6 @@ public Producer<Void> getDecodedImagePrefetchProducerSequence(
private Producer<CloseableReference<CloseableImage>> getBasicDecodedImageSequence(
ImageRequest imageRequest) {
Preconditions.checkNotNull(imageRequest);
ImageRequest.RequestLevel lowestPermittedRequestLevel =
imageRequest.getLowestPermittedRequestLevel();
Preconditions.checkState(
lowestPermittedRequestLevel.equals(ImageRequest.RequestLevel.FULL_FETCH) ||
lowestPermittedRequestLevel.equals(
ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE),
"Only support bitmap memory cache or full fetch at present, request level is %s ",
lowestPermittedRequestLevel);

if (lowestPermittedRequestLevel.equals(ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE)) {
return getBitmapCacheGetOnlySequence();
}

Uri uri = imageRequest.getSourceUri();
if (UriUtil.isNetworkUri(uri)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,14 @@ protected BitmapMemoryCacheKey getCacheKey(ImageRequest imageRequest) {
}

@Override
protected boolean shouldStartNextProducer(CloseableReference<CloseableImage> cachedResultFound) {
return !cachedResultFound.get().getQualityInfo().isOfFullQuality();
protected boolean isResultFinal(
CloseableReference<CloseableImage> cachedResultFound) {
return cachedResultFound.get().getQualityInfo().isOfFullQuality();
}

@Override
protected ImageRequest.RequestLevel getProducerRequestLevel() {
return ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,18 @@

package com.facebook.imagepipeline.producers;

import android.util.Pair;

import com.facebook.imagepipeline.cache.BitmapMemoryCacheKey;
import com.facebook.imagepipeline.cache.CacheKeyFactory;
import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.request.ImageRequest;

/**
* Multiplex producer that uses the bitmap memory cache key to combine requests.
*/
public class BitmapMemoryCacheKeyMultiplexProducer extends
MultiplexProducer<BitmapMemoryCacheKey, CloseableImage> {
MultiplexProducer<Pair<BitmapMemoryCacheKey, ImageRequest.RequestLevel>, CloseableImage> {

private final CacheKeyFactory mCacheKeyFactory;

Expand All @@ -28,8 +31,11 @@ public BitmapMemoryCacheKeyMultiplexProducer(
mCacheKeyFactory = cacheKeyFactory;
}

protected BitmapMemoryCacheKey getKey(ProducerContext producerContext) {
return mCacheKeyFactory.getBitmapCacheKey(producerContext.getImageRequest());
protected Pair<BitmapMemoryCacheKey, ImageRequest.RequestLevel> getKey(
ProducerContext producerContext) {
return Pair.create(
mCacheKeyFactory.getBitmapCacheKey(producerContext.getImageRequest()),
producerContext.getLowestPermittedRequestLevel());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,14 @@ protected BitmapMemoryCacheKey getCacheKey(ImageRequest imageRequest) {
}

@Override
protected boolean shouldStartNextProducer(CloseableReference<CloseableImage> cachedResultFound) {
return !cachedResultFound.get().getQualityInfo().isOfFullQuality();
protected boolean isResultFinal(
CloseableReference<CloseableImage> cachedResultFound) {
return cachedResultFound.get().getQualityInfo().isOfFullQuality();
}

@Override
protected ImageRequest.RequestLevel getProducerRequestLevel() {
return ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,18 @@

package com.facebook.imagepipeline.producers;

import android.util.Pair;

import com.facebook.imagepipeline.cache.CacheKeyFactory;
import com.facebook.imagepipeline.memory.PooledByteBuffer;
import com.facebook.cache.common.CacheKey;
import com.facebook.imagepipeline.request.ImageRequest;

/**
* Multiplex producer that uses the encoded cache key to combine requests.
*/
public class EncodedCacheKeyMultiplexProducer extends
MultiplexProducer<CacheKey, PooledByteBuffer> {
MultiplexProducer<Pair<CacheKey, ImageRequest.RequestLevel>, PooledByteBuffer> {

private final CacheKeyFactory mCacheKeyFactory;

Expand All @@ -26,7 +29,9 @@ public EncodedCacheKeyMultiplexProducer(CacheKeyFactory cacheKeyFactory, Produce
mCacheKeyFactory = cacheKeyFactory;
}

protected CacheKey getKey(ProducerContext producerContext) {
return mCacheKeyFactory.getEncodedCacheKey(producerContext.getImageRequest());
protected Pair<CacheKey, ImageRequest.RequestLevel> getKey(ProducerContext producerContext) {
return Pair.create(
mCacheKeyFactory.getEncodedCacheKey(producerContext.getImageRequest()),
producerContext.getLowestPermittedRequestLevel());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,14 @@ protected CacheKey getCacheKey(ImageRequest imageRequest) {
}

@Override
protected boolean shouldStartNextProducer(
protected boolean isResultFinal(
CloseableReference<PooledByteBuffer> cachedResultFound) {
return false;
return true;
}

@Override
protected ImageRequest.RequestLevel getProducerRequestLevel() {
return ImageRequest.RequestLevel.ENCODED_MEMORY_CACHE;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,26 +52,35 @@ public void produceResults(
final K cacheKey = getCacheKey(producerContext.getImageRequest());
CloseableReference<T> cachedReference = mMemoryCache.get(cacheKey, null);
if (cachedReference != null) {
boolean shouldStartNextProducer = shouldStartNextProducer(cachedReference);
boolean isLast = !shouldStartNextProducer;
boolean isLast = isResultFinal(cachedReference);
if (isLast) {
listener.onProducerFinishWithSuccess(
requestId,
getProducerName(),
listener.requiresExtraMap(requestId) ?
ImmutableMap.of(CACHED_VALUE_FOUND, "true") :
null);
}
if (isLast) {
consumer.onProgressUpdate(1f);
}
consumer.onNewResult(cachedReference, isLast);
cachedReference.close();
if (!shouldStartNextProducer) {
if (isLast) {
return;
}
}

if (producerContext.getLowestPermittedRequestLevel().getValue() >=
getProducerRequestLevel().getValue()) {
listener.onProducerFinishWithSuccess(
requestId,
getProducerName(),
listener.requiresExtraMap(requestId) ?
ImmutableMap.of(CACHED_VALUE_FOUND, "false") :
null);
consumer.onNewResult(null, true);
return;
}

Consumer<CloseableReference<T>> consumerOfNextProducer;
if (!shouldCacheReturnedValues()) {
consumerOfNextProducer = consumer;
Expand Down Expand Up @@ -107,7 +116,9 @@ public void onNewResultImpl(CloseableReference<T> newResult, boolean isLast) {

protected abstract K getCacheKey(ImageRequest imageRequest);

protected abstract boolean shouldStartNextProducer(CloseableReference<T> cachedResultFound);
protected abstract boolean isResultFinal(CloseableReference<T> cachedResultFound);

protected abstract ImageRequest.RequestLevel getProducerRequestLevel();

protected abstract boolean shouldCacheReturnedValues();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ private void startNextProducerIfHasAttachedConsumers() {
producerContext.getId(),
producerContext.getListener(),
producerContext.getCallerContext(),
producerContext.getLowestPermittedRequestLevel(),
isPrefetch(),
isIntermediateResultExpected(),
getPriority());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ public interface ProducerContext {
*/
public Object getCallerContext();

/**
* @return the lowest permitted {@link ImageRequest.RequestLevel}
*/
public ImageRequest.RequestLevel getLowestPermittedRequestLevel();

/**
* @return true if the request is a prefetch, false otherwise.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class SettableProducerContext implements ProducerContext {
private final String mId;
private final ProducerListener mProducerListener;
private final Object mCallerContext;
private final ImageRequest.RequestLevel mLowestPermittedRequestLevel;
@GuardedBy("this")
private final List<ProducerContextCallbacks> mCallbacks;
@GuardedBy("this")
Expand All @@ -46,13 +47,15 @@ public SettableProducerContext(
String id,
ProducerListener producerListener,
Object callerContext,
ImageRequest.RequestLevel lowestPermittedRequestLevel,
boolean isPrefetch,
boolean isIntermediateResultExpected,
Priority priority) {
mImageRequest = Preconditions.checkNotNull(imageRequest);
mId = Preconditions.checkNotNull(id);
mProducerListener = Preconditions.checkNotNull(producerListener);
mCallerContext = callerContext;
mLowestPermittedRequestLevel = Preconditions.checkNotNull(lowestPermittedRequestLevel);
mIsPrefetch = isPrefetch;
mIsIntermediateResultExpected = isIntermediateResultExpected;
mPriority = priority;
Expand Down Expand Up @@ -80,6 +83,11 @@ public Object getCallerContext() {
return mCallerContext;
}

@Override
public ImageRequest.RequestLevel getLowestPermittedRequestLevel() {
return mLowestPermittedRequestLevel;
}

@Override
public synchronized boolean isPrefetch() {
return mIsPrefetch;
Expand Down
Loading

0 comments on commit 2adb237

Please sign in to comment.