diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java index fdae0e2db..731da55d2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java @@ -163,8 +163,7 @@ public class ReactImageManager extends SimpleViewManager { ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_LOAD), MapBuilder.of("registrationName", "onLoad"), ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_LOAD_END), - MapBuilder.of("registrationName", "onLoadEnd") - ); + MapBuilder.of("registrationName", "onLoadEnd")); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java index 7102b8738..9cda9d0f1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java @@ -28,7 +28,6 @@ import android.graphics.RectF; import android.graphics.Shader; import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; -import android.net.Uri; import com.facebook.common.util.UriUtil; import com.facebook.csslayout.CSSConstants; @@ -51,7 +50,6 @@ import com.facebook.imagepipeline.request.BasePostprocessor; import com.facebook.imagepipeline.request.ImageRequest; import com.facebook.imagepipeline.request.ImageRequestBuilder; import com.facebook.imagepipeline.request.Postprocessor; -import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; @@ -59,6 +57,7 @@ import com.facebook.react.common.SystemClock; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.events.EventDispatcher; +import com.facebook.react.views.imagehelper.ImageSource; import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper; /** @@ -143,62 +142,6 @@ public class ReactImageView extends GenericDraweeView { } } - private class ImageSource { - private @Nullable Uri mUri; - private String mSource; - private double mSize; - private boolean mIsLocalImage; - - public ImageSource(String source, double width, double height) { - mSource = source; - mSize = width * height; - } - - public ImageSource(String source) { - this(source, 0.0d, 0.0d); - } - - public String getSource() { - return mSource; - } - - public Uri getUri() { - if (mUri == null) { - computeUri(); - } - return Assertions.assertNotNull(mUri); - } - - public double getSize() { - return mSize; - } - - public boolean isLocalImage() { - if (mUri == null) { - computeUri(); - } - return mIsLocalImage; - } - - private void computeUri() { - try { - mUri = Uri.parse(mSource); - // Verify scheme is set, so that relative uri (used by static resources) are not handled. - if (mUri.getScheme() == null) { - mUri = null; - } - } catch (Exception e) { - // ignore malformed uri, then attempt to extract resource ID. - } - if (mUri == null) { - mUri = ResourceDrawableIdHelper.getInstance().getResourceDrawableUri(getContext(), mSource); - mIsLocalImage = true; - } else { - mIsLocalImage = false; - } - } - } - private final List mSources; private @Nullable ImageSource mImageSource; @@ -249,8 +192,7 @@ public class ReactImageView extends GenericDraweeView { @Override public void onSubmit(String id, Object callerContext) { mEventDispatcher.dispatchEvent( - new ImageLoadEvent(getId(), SystemClock.nanoTime(), ImageLoadEvent.ON_LOAD_START) - ); + new ImageLoadEvent(getId(), SystemClock.nanoTime(), ImageLoadEvent.ON_LOAD_START)); } @Override @@ -260,22 +202,18 @@ public class ReactImageView extends GenericDraweeView { @Nullable Animatable animatable) { if (imageInfo != null) { mEventDispatcher.dispatchEvent( - new ImageLoadEvent(getId(), SystemClock.nanoTime(), ImageLoadEvent.ON_LOAD) - ); + new ImageLoadEvent(getId(), SystemClock.nanoTime(), ImageLoadEvent.ON_LOAD)); mEventDispatcher.dispatchEvent( - new ImageLoadEvent(getId(), SystemClock.nanoTime(), ImageLoadEvent.ON_LOAD_END) - ); + new ImageLoadEvent(getId(), SystemClock.nanoTime(), ImageLoadEvent.ON_LOAD_END)); } } @Override public void onFailure(String id, Throwable throwable) { mEventDispatcher.dispatchEvent( - new ImageLoadEvent(getId(), SystemClock.nanoTime(), ImageLoadEvent.ON_ERROR) - ); + new ImageLoadEvent(getId(), SystemClock.nanoTime(), ImageLoadEvent.ON_ERROR)); mEventDispatcher.dispatchEvent( - new ImageLoadEvent(getId(), SystemClock.nanoTime(), ImageLoadEvent.ON_LOAD_END) - ); + new ImageLoadEvent(getId(), SystemClock.nanoTime(), ImageLoadEvent.ON_LOAD_END)); } }; } @@ -327,11 +265,12 @@ public class ReactImageView extends GenericDraweeView { if (sources != null && sources.size() != 0) { // Optimize for the case where we have just one uri, case in which we don't need the sizes if (sources.size() == 1) { - mSources.add(new ImageSource(sources.getMap(0).getString("uri"))); + mSources.add(new ImageSource(getContext(), sources.getMap(0).getString("uri"))); } else { for (int idx = 0; idx < sources.size(); idx++) { ReadableMap source = sources.getMap(idx); mSources.add(new ImageSource( + getContext(), source.getString("uri"), source.getDouble("width"), source.getDouble("height"))); @@ -420,7 +359,7 @@ public class ReactImageView extends GenericDraweeView { hierarchy.setFadeDuration( mFadeDurationMs >= 0 ? mFadeDurationMs - : mImageSource.isLocalImage() ? 0 : REMOTE_IMAGE_FADE_DURATION_MS); + : mImageSource.isResource() ? 0 : REMOTE_IMAGE_FADE_DURATION_MS); Postprocessor postprocessor = usePostprocessorScaling ? mRoundedCornerPostprocessor : null; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ImageSource.java b/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ImageSource.java new file mode 100644 index 000000000..9a914cb66 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ImageSource.java @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +package com.facebook.react.views.imagehelper; + +import javax.annotation.Nullable; + +import android.content.Context; +import android.net.Uri; + +import com.facebook.infer.annotation.Assertions; + +/** + * Class describing an image source (network URI or resource) and size. + */ +public class ImageSource { + + private @Nullable Uri mUri; + private String mSource; + private double mSize; + private boolean isResource; + + public ImageSource(Context context, String source, double width, double height) { + mSource = source; + mSize = width * height; + + // Important: we compute the URI here so that we don't need to hold a reference to the context, + // potentially causing leaks. + mUri = computeUri(context); + } + + public ImageSource(Context context, String source) { + this(context, source, 0.0d, 0.0d); + } + + /** + * Get the source of this image, as it was passed to the constructor. + */ + public String getSource() { + return mSource; + } + + /** + * Get the URI for this image - can be either a parsed network URI or a resource URI. + */ + public Uri getUri() { + return Assertions.assertNotNull(mUri); + } + + /** + * Get the area of this image. + */ + public double getSize() { + return mSize; + } + + /** + * Get whether this image source represents an Android resource or a network URI. + */ + public boolean isResource() { + return isResource; + } + + private Uri computeUri(Context context) { + try { + Uri uri = Uri.parse(mSource); + // Verify scheme is set, so that relative uri (used by static resources) are not handled. + return uri.getScheme() == null ? computeLocalUri(context) : uri; + } catch (Exception e) { + return computeLocalUri(context); + } + } + + private Uri computeLocalUri(Context context) { + isResource = true; + return ResourceDrawableIdHelper.getInstance().getResourceDrawableUri(context, mSource); + } +}