From fc622504dec5b58b9ab1edc19ef605781d123129 Mon Sep 17 00:00:00 2001 From: Andrei Coman Date: Thu, 16 Jun 2016 07:13:58 -0700 Subject: [PATCH] Show low res image if available in cache Summary: Nodes version of D3392751. Reviewed By: ahmedre Differential Revision: D3425740 --- .../react/flat/DrawImageWithDrawee.java | 22 ++++++++++------ .../react/flat/DrawImageWithPipeline.java | 13 +++++----- .../react/flat/DraweeRequestHelper.java | 21 ++++++++++------ .../react/flat/MultiSourceImageHelper.java | 25 +++++++++++++++++-- 4 files changed, 57 insertions(+), 24 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithDrawee.java b/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithDrawee.java index b5a477b9b..cfb2f00c8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithDrawee.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithDrawee.java @@ -40,7 +40,6 @@ import com.facebook.react.views.image.ReactImageView; implements DrawImage, ControllerListener { private @Nullable Map mSources; - private @Nullable String mImageSource; private @Nullable Context mContext; private @Nullable DraweeRequestHelper mRequestHelper; private @Nullable PorterDuffColorFilter mColorFilter; @@ -228,18 +227,25 @@ import com.facebook.react.views.image.ReactImageView; } private void computeRequestHelper() { - mImageSource = getSourceImage(); - if (mImageSource == null) { + String[] imageSources = getImageSources(); + if (imageSources == null) { mRequestHelper = null; return; } ImageRequest imageRequest = - ImageRequestHelper.createImageRequest(Assertions.assertNotNull(mContext), - mImageSource); - mRequestHelper = new DraweeRequestHelper(Assertions.assertNotNull(imageRequest), this); + ImageRequestHelper.createImageRequest(Assertions.assertNotNull(mContext), imageSources[0]); + + ImageRequest cachedImageRequest = null; + if (imageSources.length >= 2 && imageSources[1] != null) { + cachedImageRequest = ImageRequestHelper.createImageRequest( + Assertions.assumeNotNull(mContext), + imageSources[1]); + } + mRequestHelper = new + DraweeRequestHelper(Assertions.assertNotNull(imageRequest), cachedImageRequest, this); } - private @Nullable String getSourceImage() { + private @Nullable String[] getImageSources() { if (mSources == null || mSources.isEmpty()) { return null; } @@ -247,7 +253,7 @@ import com.facebook.react.views.image.ReactImageView; final double targetImageSize = (getRight() - getLeft()) * (getBottom() - getTop()); return MultiSourceImageHelper.getImageSourceFromMultipleSources(targetImageSize, mSources); } - return mSources.keySet().iterator().next(); + return new String[]{mSources.keySet().iterator().next()}; } private boolean hasMultipleSources() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithPipeline.java b/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithPipeline.java index 070b8f159..a9467d065 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithPipeline.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithPipeline.java @@ -44,7 +44,6 @@ import com.facebook.react.views.image.ReactImageView; private static final int BORDER_BITMAP_PATH_DIRTY = 1 << 1; private @Nullable Map mSources; - private @Nullable String mImageSource; private @Nullable Context mContext; private final Matrix mTransform = new Matrix(); private ScaleType mScaleType = ImageResizeMode.defaultValue(); @@ -226,18 +225,18 @@ import com.facebook.react.views.image.ReactImageView; } private void computeRequestHelper() { - mImageSource = getSourceImage(); - if (mImageSource == null) { + String[] imageSources = getImageSources(); + if (imageSources == null) { mRequestHelper = null; return; } ImageRequest imageRequest = - ImageRequestHelper.createImageRequest(Assertions.assertNotNull(mContext), - mImageSource); + ImageRequestHelper.createImageRequest(Assertions.assertNotNull(mContext), imageSources[0]); + // DrawImageWithPipeline does now support displaying low res cache images before request mRequestHelper = new PipelineRequestHelper(Assertions.assertNotNull(imageRequest)); } - private String getSourceImage() { + private @Nullable String[] getImageSources() { if (mSources == null || mSources.isEmpty()) { return null; } @@ -245,7 +244,7 @@ import com.facebook.react.views.image.ReactImageView; final double targetImageSize = (getRight() - getLeft()) * (getBottom() - getTop()); return MultiSourceImageHelper.getImageSourceFromMultipleSources(targetImageSize, mSources); } - return mSources.keySet().iterator().next(); + return new String[]{mSources.keySet().iterator().next()}; } private boolean hasMultipleSources() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/DraweeRequestHelper.java b/ReactAndroid/src/main/java/com/facebook/react/flat/DraweeRequestHelper.java index 2fcd06979..89f4ef236 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/DraweeRequestHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/DraweeRequestHelper.java @@ -9,6 +9,7 @@ package com.facebook.react.flat; +import javax.annotation.Nullable; import android.content.res.Resources; import android.graphics.drawable.Drawable; @@ -18,7 +19,6 @@ import com.facebook.drawee.controller.ControllerListener; import com.facebook.drawee.generic.GenericDraweeHierarchy; import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; import com.facebook.drawee.interfaces.DraweeController; -import com.facebook.drawee.interfaces.DraweeController; import com.facebook.imagepipeline.request.ImageRequest; import com.facebook.infer.annotation.Assertions; @@ -38,12 +38,19 @@ import com.facebook.infer.annotation.Assertions; private final DraweeController mDraweeController; private int mAttachCounter; - /* package */ DraweeRequestHelper(ImageRequest imageRequest, ControllerListener listener) { - DraweeController controller = sControllerBuilder - .setImageRequest(imageRequest) - .setCallerContext(RCTImageView.getCallerContext()) - .setControllerListener(listener) - .build(); + /* package */ DraweeRequestHelper( + ImageRequest imageRequest, + @Nullable ImageRequest cachedImageRequest, + ControllerListener listener) { + AbstractDraweeControllerBuilder controllerBuilder = sControllerBuilder + .setImageRequest(imageRequest) + .setCallerContext(RCTImageView.getCallerContext()) + .setControllerListener(listener); + + if (cachedImageRequest != null) { + controllerBuilder.setLowResImageRequest(cachedImageRequest); + } + DraweeController controller = controllerBuilder.build(); controller.setHierarchy(sHierarchyBuilder.build()); diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/MultiSourceImageHelper.java b/ReactAndroid/src/main/java/com/facebook/react/flat/MultiSourceImageHelper.java index 082094053..dca808646 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/MultiSourceImageHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/MultiSourceImageHelper.java @@ -13,6 +13,11 @@ import javax.annotation.Nullable; import java.util.Map; +import android.net.Uri; + +import com.facebook.imagepipeline.core.ImagePipeline; +import com.facebook.imagepipeline.core.ImagePipelineFactory; + /** * Helper class for computing the source to be used for an Image. */ @@ -23,18 +28,34 @@ import java.util.Map; * after the layout pass when the sizes of the target image have been computed, and when there * are at least two sources to choose from. */ - public static @Nullable String getImageSourceFromMultipleSources( + public static @Nullable String[] getImageSourceFromMultipleSources( double targetImageSize, Map sources) { + ImagePipeline imagePipeline = ImagePipelineFactory.getInstance().getImagePipeline(); double bestPrecision = Double.MAX_VALUE; + double bestCachePrecision = Double.MAX_VALUE; String imageSource = null; + String cachedImageSource = null; for (Map.Entry source : sources.entrySet()) { final double precision = Math.abs(1.0 - (source.getValue()) / targetImageSize); if (precision < bestPrecision) { bestPrecision = precision; imageSource = source.getKey(); } + + Uri sourceUri = Uri.parse(source.getKey()); + if (precision < bestCachePrecision && + (imagePipeline.isInBitmapMemoryCache(sourceUri) || + imagePipeline.isInDiskCacheSync(sourceUri))) { + bestCachePrecision = precision; + cachedImageSource = source.getKey(); + } } - return imageSource; + + // don't use cached image source if it's the same as the image source + if (cachedImageSource != null && cachedImageSource.equals(imageSource)) { + cachedImageSource = null; + } + return new String[]{imageSource, cachedImageSource}; } }