From ced8a98b9ffa3612656b7979f8933ae9cf19d657 Mon Sep 17 00:00:00 2001 From: Ralph Bergmann Date: Mon, 16 Dec 2013 19:23:26 +0100 Subject: Use the view size and scale type to restrict NIV requests. Change-Id: I77e705c09937f78af746cd73b6e6d94fd4ee2a03 --- .../com/android/volley/toolbox/ImageLoader.java | 16 ++++++---- .../com/android/volley/toolbox/ImageRequest.java | 37 ++++++++++++++++++---- .../android/volley/toolbox/NetworkImageView.java | 3 +- 3 files changed, 42 insertions(+), 14 deletions(-) (limited to 'src/main/java/com/android/volley') diff --git a/src/main/java/com/android/volley/toolbox/ImageLoader.java b/src/main/java/com/android/volley/toolbox/ImageLoader.java index 5348dc6..6dc86bb 100644 --- a/src/main/java/com/android/volley/toolbox/ImageLoader.java +++ b/src/main/java/com/android/volley/toolbox/ImageLoader.java @@ -20,6 +20,7 @@ import android.graphics.Bitmap.Config; import android.os.Handler; import android.os.Looper; import android.widget.ImageView; +import android.widget.ImageView.ScaleType; import com.android.volley.Request; import com.android.volley.RequestQueue; @@ -167,7 +168,7 @@ public class ImageLoader { * @param defaultImage Optional default image to return until the actual image is loaded. */ public ImageContainer get(String requestUrl, final ImageListener listener) { - return get(requestUrl, listener, 0, 0); + return get(requestUrl, listener, 0, 0, ScaleType.CENTER_INSIDE); } /** @@ -179,11 +180,13 @@ public class ImageLoader { * @param imageListener The listener to call when the remote image is loaded * @param maxWidth The maximum width of the returned image. * @param maxHeight The maximum height of the returned image. + * @param scaleType The ImageViews ScaleType used to calculate the needed image size. * @return A container object that contains all of the properties of the request, as well as * the currently available image (default if remote is not loaded). */ public ImageContainer get(String requestUrl, ImageListener imageListener, - int maxWidth, int maxHeight) { + int maxWidth, int maxHeight, ScaleType scaleType) { + // only fulfill requests that were initiated from the main thread. throwIfNotOnMainThread(); @@ -215,7 +218,8 @@ public class ImageLoader { // The request is not already in flight. Send the new request to the network and // track it. - Request newRequest = makeImageRequest(requestUrl, maxWidth, maxHeight, cacheKey); + Request newRequest = makeImageRequest(requestUrl, maxWidth, maxHeight, scaleType, + cacheKey); mRequestQueue.add(newRequest); mInFlightRequests.put(cacheKey, @@ -223,14 +227,14 @@ public class ImageLoader { return imageContainer; } - protected Request makeImageRequest(String requestUrl, int maxWidth, int maxHeight, final String cacheKey) { + protected Request makeImageRequest(String requestUrl, int maxWidth, int maxHeight, + ScaleType scaleType, final String cacheKey) { return new ImageRequest(requestUrl, new Listener() { @Override public void onResponse(Bitmap response) { onGetImageSuccess(cacheKey, response); } - }, maxWidth, maxHeight, - Config.RGB_565, new ErrorListener() { + }, maxWidth, maxHeight, scaleType, Config.RGB_565, new ErrorListener() { @Override public void onErrorResponse(VolleyError error) { onGetImageError(cacheKey, error); diff --git a/src/main/java/com/android/volley/toolbox/ImageRequest.java b/src/main/java/com/android/volley/toolbox/ImageRequest.java index 2ebe015..8a09ea1 100644 --- a/src/main/java/com/android/volley/toolbox/ImageRequest.java +++ b/src/main/java/com/android/volley/toolbox/ImageRequest.java @@ -26,6 +26,7 @@ import com.android.volley.VolleyLog; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; +import android.widget.ImageView.ScaleType; /** * A canned request for getting an image at a given URL and calling @@ -45,6 +46,7 @@ public class ImageRequest extends Request { private final Config mDecodeConfig; private final int mMaxWidth; private final int mMaxHeight; + private ScaleType mScaleType; /** Decoding lock so that we don't decode more than one image at a time (to avoid OOM's) */ private static final Object sDecodeLock = new Object(); @@ -63,18 +65,20 @@ public class ImageRequest extends Request { * @param maxWidth Maximum width to decode this bitmap to, or zero for none * @param maxHeight Maximum height to decode this bitmap to, or zero for * none + * @param scaleType The ImageViews ScaleType used to calculate the needed image size. * @param decodeConfig Format to decode the bitmap to * @param errorListener Error listener, or null to ignore errors */ public ImageRequest(String url, Response.Listener listener, int maxWidth, int maxHeight, - Config decodeConfig, Response.ErrorListener errorListener) { - super(Method.GET, url, errorListener); + ScaleType scaleType, Config decodeConfig, Response.ErrorListener errorListener) { + super(Method.GET, url, errorListener); setRetryPolicy( new DefaultRetryPolicy(IMAGE_TIMEOUT_MS, IMAGE_MAX_RETRIES, IMAGE_BACKOFF_MULT)); mListener = listener; mDecodeConfig = decodeConfig; mMaxWidth = maxWidth; mMaxHeight = maxHeight; + mScaleType = scaleType; } @Override @@ -92,14 +96,24 @@ public class ImageRequest extends Request { * maintain aspect ratio with primary dimension * @param actualPrimary Actual size of the primary dimension * @param actualSecondary Actual size of the secondary dimension + * @param scaleType The ScaleType used to calculate the needed image size. */ private static int getResizedDimension(int maxPrimary, int maxSecondary, int actualPrimary, - int actualSecondary) { + int actualSecondary, ScaleType scaleType) { + // If no dominant value at all, just return the actual. - if (maxPrimary == 0 && maxSecondary == 0) { + if ((maxPrimary == 0) && (maxSecondary == 0)) { return actualPrimary; } + // If ScaleType.FIT_XY fill the whole rectangle, ignore ratio. + if (scaleType == ScaleType.FIT_XY) { + if (maxPrimary == 0) { + return actualPrimary; + } + return maxPrimary; + } + // If primary is unspecified, scale primary to match secondary's scaling ratio. if (maxPrimary == 0) { double ratio = (double) maxSecondary / (double) actualSecondary; @@ -112,7 +126,16 @@ public class ImageRequest extends Request { double ratio = (double) actualSecondary / (double) actualPrimary; int resized = maxPrimary; - if (resized * ratio > maxSecondary) { + + // If ScaleType.CENTER_CROP fill the whole rectangle, preserve aspect ratio. + if (scaleType == ScaleType.CENTER_CROP) { + if ((resized * ratio) < maxSecondary) { + resized = (int) (maxSecondary / ratio); + } + return resized; + } + + if ((resized * ratio) > maxSecondary) { resized = (int) (maxSecondary / ratio); } return resized; @@ -150,9 +173,9 @@ public class ImageRequest extends Request { // Then compute the dimensions we would ideally like to decode to. int desiredWidth = getResizedDimension(mMaxWidth, mMaxHeight, - actualWidth, actualHeight); + actualWidth, actualHeight, mScaleType); int desiredHeight = getResizedDimension(mMaxHeight, mMaxWidth, - actualHeight, actualWidth); + actualHeight, actualWidth, mScaleType); // Decode to the nearest power of two scaling factor. decodeOptions.inJustDecodeBounds = false; diff --git a/src/main/java/com/android/volley/toolbox/NetworkImageView.java b/src/main/java/com/android/volley/toolbox/NetworkImageView.java index 692e988..324dbc0 100644 --- a/src/main/java/com/android/volley/toolbox/NetworkImageView.java +++ b/src/main/java/com/android/volley/toolbox/NetworkImageView.java @@ -103,6 +103,7 @@ public class NetworkImageView extends ImageView { void loadImageIfNecessary(final boolean isInLayoutPass) { int width = getWidth(); int height = getHeight(); + ScaleType scaleType = getScaleType(); boolean wrapWidth = false, wrapHeight = false; if (getLayoutParams() != null) { @@ -177,7 +178,7 @@ public class NetworkImageView extends ImageView { setImageResource(mDefaultImageId); } } - }, maxWidth, maxHeight); + }, maxWidth, maxHeight, scaleType); // update the ImageContainer to be the new bitmap container. mImageContainer = newContainer; -- cgit v1.2.3