aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRalph Bergmann <ralph@the4thfloor.eu>2013-12-16 19:23:26 +0100
committerRalph Bergmann <ralph@the4thfloor.eu>2014-12-15 12:54:08 +0100
commitced8a98b9ffa3612656b7979f8933ae9cf19d657 (patch)
treeba375755aaaa02798bf436a9ac2b22f314404ca2 /src
parent1a39583f0ee06329f7918ed9a4c7d0e7cd342917 (diff)
downloadvolley-ced8a98b9ffa3612656b7979f8933ae9cf19d657.tar.gz
Use the view size and scale type to restrict NIV requests.
Change-Id: I77e705c09937f78af746cd73b6e6d94fd4ee2a03
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/android/volley/toolbox/ImageLoader.java16
-rw-r--r--src/main/java/com/android/volley/toolbox/ImageRequest.java37
-rw-r--r--src/main/java/com/android/volley/toolbox/NetworkImageView.java3
-rw-r--r--src/test/java/com/android/volley/toolbox/ImageRequestTest.java86
-rw-r--r--src/test/java/com/android/volley/toolbox/NetworkImageViewTest.java3
5 files changed, 114 insertions, 31 deletions
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<Bitmap> newRequest = makeImageRequest(requestUrl, maxWidth, maxHeight, cacheKey);
+ Request<Bitmap> newRequest = makeImageRequest(requestUrl, maxWidth, maxHeight, scaleType,
+ cacheKey);
mRequestQueue.add(newRequest);
mInFlightRequests.put(cacheKey,
@@ -223,14 +227,14 @@ public class ImageLoader {
return imageContainer;
}
- protected Request<Bitmap> makeImageRequest(String requestUrl, int maxWidth, int maxHeight, final String cacheKey) {
+ protected Request<Bitmap> makeImageRequest(String requestUrl, int maxWidth, int maxHeight,
+ ScaleType scaleType, final String cacheKey) {
return new ImageRequest(requestUrl, new Listener<Bitmap>() {
@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<Bitmap> {
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<Bitmap> {
* @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<Bitmap> 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<Bitmap> {
* 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<Bitmap> {
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<Bitmap> {
// 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;
diff --git a/src/test/java/com/android/volley/toolbox/ImageRequestTest.java b/src/test/java/com/android/volley/toolbox/ImageRequestTest.java
index 2f4495a..bd98e7d 100644
--- a/src/test/java/com/android/volley/toolbox/ImageRequestTest.java
+++ b/src/test/java/com/android/volley/toolbox/ImageRequestTest.java
@@ -18,7 +18,7 @@ package com.android.volley.toolbox;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
-
+import android.widget.ImageView.ScaleType;
import com.android.volley.NetworkResponse;
import com.android.volley.Response;
import org.junit.Test;
@@ -47,30 +47,84 @@ public class ImageRequestTest {
ShadowBitmapFactory.provideWidthAndHeightHints("fake", 1024, 500);
NetworkResponse jpeg = new NetworkResponse(jpegBytes);
- // No resize
- verifyResize(jpeg, 0, 0, 1024, 500);
+ // Scale the image uniformly (maintain the image's aspect ratio) so that
+ // both dimensions (width and height) of the image will be equal to or
+ // less than the corresponding dimension of the view.
+ ScaleType scalteType = ScaleType.CENTER_INSIDE;
// Exact sizes
- verifyResize(jpeg, 512, 250, 512, 250); // exactly half
- verifyResize(jpeg, 511, 249, 509, 249); // just under half
- verifyResize(jpeg, 1080, 500, 1024, 500); // larger
- verifyResize(jpeg, 500, 500, 500, 244); // keep same ratio
+ verifyResize(jpeg, 512, 250, scalteType, 512, 250); // exactly half
+ verifyResize(jpeg, 511, 249, scalteType, 509, 249); // just under half
+ verifyResize(jpeg, 1080, 500, scalteType, 1024, 500); // larger
+ verifyResize(jpeg, 500, 500, scalteType, 500, 244); // keep same ratio
// Specify only width, preserve aspect ratio
- verifyResize(jpeg, 512, 0, 512, 250);
- verifyResize(jpeg, 800, 0, 800, 390);
- verifyResize(jpeg, 1024, 0, 1024, 500);
+ verifyResize(jpeg, 512, 0, scalteType, 512, 250);
+ verifyResize(jpeg, 800, 0, scalteType, 800, 390);
+ verifyResize(jpeg, 1024, 0, scalteType, 1024, 500);
// Specify only height, preserve aspect ratio
- verifyResize(jpeg, 0, 250, 512, 250);
- verifyResize(jpeg, 0, 391, 800, 391);
- verifyResize(jpeg, 0, 500, 1024, 500);
+ verifyResize(jpeg, 0, 250, scalteType, 512, 250);
+ verifyResize(jpeg, 0, 391, scalteType, 800, 391);
+ verifyResize(jpeg, 0, 500, scalteType, 1024, 500);
+
+ // No resize
+ verifyResize(jpeg, 0, 0, scalteType, 1024, 500);
+
+
+ // Scale the image uniformly (maintain the image's aspect ratio) so that
+ // both dimensions (width and height) of the image will be equal to or
+ // larger than the corresponding dimension of the view.
+ scalteType = ScaleType.CENTER_CROP;
+
+ // Exact sizes
+ verifyResize(jpeg, 512, 250, scalteType, 512, 250);
+ verifyResize(jpeg, 511, 249, scalteType, 511, 249);
+ verifyResize(jpeg, 1080, 500, scalteType, 1024, 500);
+ verifyResize(jpeg, 500, 500, scalteType, 1024, 500);
+
+ // Specify only width
+ verifyResize(jpeg, 512, 0, scalteType, 512, 250);
+ verifyResize(jpeg, 800, 0, scalteType, 800, 390);
+ verifyResize(jpeg, 1024, 0, scalteType, 1024, 500);
+
+ // Specify only height
+ verifyResize(jpeg, 0, 250, scalteType, 512, 250);
+ verifyResize(jpeg, 0, 391, scalteType, 800, 391);
+ verifyResize(jpeg, 0, 500, scalteType, 1024, 500);
+
+ // No resize
+ verifyResize(jpeg, 0, 0, scalteType, 1024, 500);
+
+
+ // Scale in X and Y independently, so that src matches dst exactly. This
+ // may change the aspect ratio of the src.
+ scalteType = ScaleType.FIT_XY;
+
+ // Exact sizes
+ verifyResize(jpeg, 512, 250, scalteType, 512, 250);
+ verifyResize(jpeg, 511, 249, scalteType, 511, 249);
+ verifyResize(jpeg, 1080, 500, scalteType, 1024, 500);
+ verifyResize(jpeg, 500, 500, scalteType, 500, 500);
+
+ // Specify only width
+ verifyResize(jpeg, 512, 0, scalteType, 512, 500);
+ verifyResize(jpeg, 800, 0, scalteType, 800, 500);
+ verifyResize(jpeg, 1024, 0, scalteType, 1024, 500);
+
+ // Specify only height
+ verifyResize(jpeg, 0, 250, scalteType, 1024, 250);
+ verifyResize(jpeg, 0, 391, scalteType, 1024, 391);
+ verifyResize(jpeg, 0, 500, scalteType, 1024, 500);
+
+ // No resize
+ verifyResize(jpeg, 0, 0, scalteType, 1024, 500);
}
private void verifyResize(NetworkResponse networkResponse, int maxWidth, int maxHeight,
- int expectedWidth, int expectedHeight) {
- ImageRequest request = new ImageRequest(
- "", null, maxWidth, maxHeight, Config.RGB_565, null);
+ ScaleType scaleType, int expectedWidth, int expectedHeight) {
+ ImageRequest request = new ImageRequest("", null, maxWidth, maxHeight, scaleType,
+ Config.RGB_565, null);
Response<Bitmap> response = request.parseNetworkResponse(networkResponse);
assertNotNull(response);
assertTrue(response.isSuccess());
diff --git a/src/test/java/com/android/volley/toolbox/NetworkImageViewTest.java b/src/test/java/com/android/volley/toolbox/NetworkImageViewTest.java
index 48c81b6..bc2cc29 100644
--- a/src/test/java/com/android/volley/toolbox/NetworkImageViewTest.java
+++ b/src/test/java/com/android/volley/toolbox/NetworkImageViewTest.java
@@ -1,6 +1,7 @@
package com.android.volley.toolbox;
import android.view.ViewGroup.LayoutParams;
+import android.widget.ImageView.ScaleType;
import org.junit.Before;
import org.junit.Test;
@@ -43,7 +44,7 @@ public class NetworkImageViewTest {
public int lastMaxHeight;
public ImageContainer get(String requestUrl, ImageListener imageListener, int maxWidth,
- int maxHeight) {
+ int maxHeight, ScaleType scaleType) {
lastRequestUrl = requestUrl;
lastMaxWidth = maxWidth;
lastMaxHeight = maxHeight;