From c2cd53fe5f170f23dde57590233d05612fd0edd9 Mon Sep 17 00:00:00 2001 From: Alexander Djenkov Date: Thu, 15 Mar 2018 16:39:01 +0200 Subject: [PATCH] fix(cache-images): respect decodeWidth and decodeHeight when caching images (#115) * feat(image-fetcher): limit bitmap to device sizes when no request width/height set. * fix(cache-images): create new cache for images with different decodeHeight/decodeWidth. --- .../nativescript/widgets/Image/Fetcher.java | 11 +++++--- .../nativescript/widgets/Image/Worker.java | 27 +++++++++++++++---- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/android/widgets/src/main/java/org/nativescript/widgets/Image/Fetcher.java b/android/widgets/src/main/java/org/nativescript/widgets/Image/Fetcher.java index 73007d26c..19878b6e4 100644 --- a/android/widgets/src/main/java/org/nativescript/widgets/Image/Fetcher.java +++ b/android/widgets/src/main/java/org/nativescript/widgets/Image/Fetcher.java @@ -48,6 +48,9 @@ public class Fetcher extends Worker { private static final String HTTP_CACHE_DIR = "http"; private static final int IO_BUFFER_SIZE = 8 * 1024; + private static int mDeviceWidthPixels; + private static int mDeviceHeightPixels; + private File mHttpCacheDir; private DiskLruCache mHttpDiskCache; private boolean mHttpDiskCacheStarting = true; @@ -74,6 +77,8 @@ public class Fetcher extends Worker { super(context); mHttpCacheDir = Cache.getDiskCacheDir(context, HTTP_CACHE_DIR); mPackageName = context.getPackageName(); + mDeviceWidthPixels = (int) context.getResources().getDisplayMetrics().widthPixels; + mDeviceHeightPixels = (int) context.getResources().getDisplayMetrics().heightPixels; } @Override @@ -477,15 +482,15 @@ public class Fetcher extends Worker { int sourceWidth = bitmap.getWidth(); int sourceHeight = bitmap.getHeight(); - reqWidth = reqWidth > 0 ? reqWidth : sourceWidth; - reqHeight = reqHeight > 0 ? reqHeight : sourceHeight; + reqWidth = reqWidth > 0 ? reqWidth : Math.min(sourceWidth, mDeviceWidthPixels); + reqHeight = reqHeight > 0 ? reqHeight : Math.min(sourceHeight, mDeviceHeightPixels); // scale if (reqWidth != sourceWidth || reqHeight != sourceHeight) { if (keepAspectRatio) { double widthCoef = (double) sourceWidth / (double) reqWidth; double heightCoef = (double) sourceHeight / (double) reqHeight; - double aspectCoef = widthCoef > heightCoef ? widthCoef : heightCoef; + double aspectCoef = Math.min(widthCoef, heightCoef); reqWidth = (int) Math.floor(sourceWidth / aspectCoef); reqHeight = (int) Math.floor(sourceHeight / aspectCoef); diff --git a/android/widgets/src/main/java/org/nativescript/widgets/Image/Worker.java b/android/widgets/src/main/java/org/nativescript/widgets/Image/Worker.java index 7ef53e669..2d940d597 100644 --- a/android/widgets/src/main/java/org/nativescript/widgets/Image/Worker.java +++ b/android/widgets/src/main/java/org/nativescript/widgets/Image/Worker.java @@ -101,12 +101,17 @@ public abstract class Worker { } Bitmap value = null; + String cacheUri = uri; + if (debuggable > 0) { Log.v(TAG, "loadImage on: " + owner + " to: " + uri); } if (mCache != null && useCache) { - value = mCache.getBitmapFromMemCache(uri); + // Create new image cache for images with different decodeHeight/decodeWidth. + cacheUri = createCacheUri(uri, decodeHeight, decodeWidth); + + value = mCache.getBitmapFromMemCache(cacheUri); } if (value == null && !async) { @@ -115,9 +120,9 @@ public abstract class Worker { if (value != null) { if (mCache != null && useCache) { if (debuggable > 0) { - Log.v(TAG, "loadImage.addBitmapToCache: " + owner + ", src: " + uri); + Log.v(TAG, "loadImage.addBitmapToCache: " + owner + ", src: " + cacheUri); } - mCache.addBitmapToCache(uri, value); + mCache.addBitmapToCache(cacheUri, value); } } } @@ -257,6 +262,16 @@ public abstract class Worker { return null; } + /** + * Create cache key depending on image uri and decode properties. + */ + private static String createCacheUri(String uri, int decodeHeight, int decodeWidth) { + uri += decodeHeight != 0 ? "height%%" + String.valueOf(decodeHeight): ""; + uri += decodeWidth != 0 ? "width%%" + String.valueOf(decodeWidth): ""; + + return uri; + } + /** * The actual AsyncTask that will asynchronously process the image. */ @@ -265,6 +280,7 @@ public abstract class Worker { private int mDecodeHeight; private boolean mKeepAspectRatio; private String mUri; + private String mCacheUri; private boolean mCacheImage; private final WeakReference imageViewReference; private final OnImageLoadedListener mOnImageLoadedListener; @@ -279,6 +295,7 @@ public abstract class Worker { mKeepAspectRatio = keepAspectRatio; mCacheImage = cacheImage; mUri = uri; + mCacheUri = createCacheUri(uri, decodeHeight, decodeWidth); imageViewReference = new WeakReference(owner); mOnImageLoadedListener = listener; } @@ -320,9 +337,9 @@ public abstract class Worker { if (bitmap != null) { if (mCache != null && mCacheImage) { if (debuggable > 0) { - Log.v(TAG, "addBitmapToCache: " + imageViewReference.get() + ", src: " + mUri); + Log.v(TAG, "addBitmapToCache: " + imageViewReference.get() + ", src: " + mCacheUri); } - mCache.addBitmapToCache(mUri, bitmap); + mCache.addBitmapToCache(mCacheUri, bitmap); } }