Store the original bitmap dimensions for the box art

This commit is contained in:
Cameron Gutman 2020-06-11 19:08:25 -07:00
parent 4587c1550d
commit d59e5ae9cf
4 changed files with 46 additions and 23 deletions

View File

@ -92,7 +92,7 @@ public class CachedAppAssetLoader {
memoryLoader.clearCache(); memoryLoader.clearCache();
} }
private Bitmap doNetworkAssetLoad(LoaderTuple tuple, LoaderTask task) { private ScaledBitmap doNetworkAssetLoad(LoaderTuple tuple, LoaderTask task) {
// Try 3 times // Try 3 times
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
// Check again whether we've been cancelled or the image view is gone // Check again whether we've been cancelled or the image view is gone
@ -113,7 +113,7 @@ public class CachedAppAssetLoader {
// If there's a task associated with this load, we should return the bitmap // If there's a task associated with this load, we should return the bitmap
if (task != null) { if (task != null) {
// If the cached bitmap is valid, return it. Otherwise, we'll try the load again // If the cached bitmap is valid, return it. Otherwise, we'll try the load again
Bitmap bmp = diskLoader.loadBitmapFromCache(tuple, (int) scalingDivider); ScaledBitmap bmp = diskLoader.loadBitmapFromCache(tuple, (int) scalingDivider);
if (bmp != null) { if (bmp != null) {
return bmp; return bmp;
} }
@ -135,7 +135,7 @@ public class CachedAppAssetLoader {
return null; return null;
} }
private class LoaderTask extends AsyncTask<LoaderTuple, Void, Bitmap> { private class LoaderTask extends AsyncTask<LoaderTuple, Void, ScaledBitmap> {
private final WeakReference<ImageView> imageViewRef; private final WeakReference<ImageView> imageViewRef;
private final WeakReference<ProgressBar> progressViewRef; private final WeakReference<ProgressBar> progressViewRef;
private final boolean diskOnly; private final boolean diskOnly;
@ -149,7 +149,7 @@ public class CachedAppAssetLoader {
} }
@Override @Override
protected Bitmap doInBackground(LoaderTuple... params) { protected ScaledBitmap doInBackground(LoaderTuple... params) {
tuple = params[0]; tuple = params[0];
// Check whether it has been cancelled or the views are gone // Check whether it has been cancelled or the views are gone
@ -157,7 +157,7 @@ public class CachedAppAssetLoader {
return null; return null;
} }
Bitmap bmp = diskLoader.loadBitmapFromCache(tuple, (int) scalingDivider); ScaledBitmap bmp = diskLoader.loadBitmapFromCache(tuple, (int) scalingDivider);
if (bmp == null) { if (bmp == null) {
if (!diskOnly) { if (!diskOnly) {
// Try to load the asset from the network // Try to load the asset from the network
@ -205,7 +205,7 @@ public class CachedAppAssetLoader {
} }
@Override @Override
protected void onPostExecute(final Bitmap bitmap) { protected void onPostExecute(final ScaledBitmap bitmap) {
// Do nothing if cancelled // Do nothing if cancelled
if (isCancelled()) { if (isCancelled()) {
return; return;
@ -231,7 +231,7 @@ public class CachedAppAssetLoader {
@Override @Override
public void onAnimationEnd(Animation animation) { public void onAnimationEnd(Animation animation) {
// Fade in the new box art // Fade in the new box art
imageView.setImageBitmap(bitmap); imageView.setImageBitmap(bitmap.bitmap);
imageView.setAnimation(AnimationUtils.loadAnimation(imageView.getContext(), R.anim.boxart_fadein)); imageView.setAnimation(AnimationUtils.loadAnimation(imageView.getContext(), R.anim.boxart_fadein));
} }
@ -242,7 +242,7 @@ public class CachedAppAssetLoader {
} }
else { else {
// View is invisible already, so just fade in the new art // View is invisible already, so just fade in the new art
imageView.setImageBitmap(bitmap); imageView.setImageBitmap(bitmap.bitmap);
imageView.setAnimation(AnimationUtils.loadAnimation(imageView.getContext(), R.anim.boxart_fadein)); imageView.setAnimation(AnimationUtils.loadAnimation(imageView.getContext(), R.anim.boxart_fadein));
imageView.setVisibility(View.VISIBLE); imageView.setVisibility(View.VISIBLE);
} }
@ -338,11 +338,11 @@ public class CachedAppAssetLoader {
prgView.setVisibility(View.INVISIBLE); prgView.setVisibility(View.INVISIBLE);
// First, try the memory cache in the current context // First, try the memory cache in the current context
Bitmap bmp = memoryLoader.loadBitmapFromCache(tuple); ScaledBitmap bmp = memoryLoader.loadBitmapFromCache(tuple);
if (bmp != null) { if (bmp != null) {
// Show the bitmap immediately // Show the bitmap immediately
imgView.setVisibility(View.VISIBLE); imgView.setVisibility(View.VISIBLE);
imgView.setImageBitmap(bmp); imgView.setImageBitmap(bmp.bitmap);
return true; return true;
} }

View File

@ -64,7 +64,7 @@ public class DiskAssetLoader {
return inSampleSize; return inSampleSize;
} }
public Bitmap loadBitmapFromCache(CachedAppAssetLoader.LoaderTuple tuple, int sampleSize) { public ScaledBitmap loadBitmapFromCache(CachedAppAssetLoader.LoaderTuple tuple, int sampleSize) {
File file = getFile(tuple.computer.uuid, tuple.app.getAppId()); File file = getFile(tuple.computer.uuid, tuple.app.getAppId());
// Don't bother with anything if it doesn't exist // Don't bother with anything if it doesn't exist
@ -110,27 +110,33 @@ public class DiskAssetLoader {
bmp = BitmapFactory.decodeFile(file.getAbsolutePath(), options); bmp = BitmapFactory.decodeFile(file.getAbsolutePath(), options);
if (bmp != null) { if (bmp != null) {
LimeLog.info("Tuple "+tuple+" decoded from disk cache with sample size: "+options.inSampleSize); LimeLog.info("Tuple "+tuple+" decoded from disk cache with sample size: "+options.inSampleSize);
return new ScaledBitmap(decodeOnlyOptions.outWidth, decodeOnlyOptions.outHeight, bmp);
} }
} }
else { else {
// On P, we can get a bitmap back in one step with ImageDecoder // On P, we can get a bitmap back in one step with ImageDecoder
final ScaledBitmap scaledBitmap = new ScaledBitmap();
try { try {
bmp = ImageDecoder.decodeBitmap(ImageDecoder.createSource(file), new ImageDecoder.OnHeaderDecodedListener() { scaledBitmap.bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(file), new ImageDecoder.OnHeaderDecodedListener() {
@Override @Override
public void onHeaderDecoded(ImageDecoder imageDecoder, ImageDecoder.ImageInfo imageInfo, ImageDecoder.Source source) { public void onHeaderDecoded(ImageDecoder imageDecoder, ImageDecoder.ImageInfo imageInfo, ImageDecoder.Source source) {
scaledBitmap.originalWidth = imageInfo.getSize().getWidth();
scaledBitmap.originalHeight = imageInfo.getSize().getHeight();
imageDecoder.setTargetSize(STANDARD_ASSET_WIDTH, STANDARD_ASSET_HEIGHT); imageDecoder.setTargetSize(STANDARD_ASSET_WIDTH, STANDARD_ASSET_HEIGHT);
if (isLowRamDevice) { if (isLowRamDevice) {
imageDecoder.setMemorySizePolicy(ImageDecoder.MEMORY_POLICY_LOW_RAM); imageDecoder.setMemorySizePolicy(ImageDecoder.MEMORY_POLICY_LOW_RAM);
} }
} }
}); });
return scaledBitmap;
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
return null; return null;
} }
} }
return bmp; return null;
} }
public File getFile(String computerUuid, int appId) { public File getFile(String computerUuid, int appId) {

View File

@ -1,6 +1,5 @@
package com.limelight.grid.assets; package com.limelight.grid.assets;
import android.graphics.Bitmap;
import android.util.LruCache; import android.util.LruCache;
import com.limelight.LimeLog; import com.limelight.LimeLog;
@ -10,15 +9,15 @@ import java.util.HashMap;
public class MemoryAssetLoader { public class MemoryAssetLoader {
private static final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); private static final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
private static final LruCache<String, Bitmap> memoryCache = new LruCache<String, Bitmap>(maxMemory / 16) { private static final LruCache<String, ScaledBitmap> memoryCache = new LruCache<String, ScaledBitmap>(maxMemory / 16) {
@Override @Override
protected int sizeOf(String key, Bitmap bitmap) { protected int sizeOf(String key, ScaledBitmap bitmap) {
// Sizeof returns kilobytes // Sizeof returns kilobytes
return bitmap.getByteCount() / 1024; return bitmap.bitmap.getByteCount() / 1024;
} }
@Override @Override
protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) { protected void entryRemoved(boolean evicted, String key, ScaledBitmap oldValue, ScaledBitmap newValue) {
super.entryRemoved(evicted, key, oldValue, newValue); super.entryRemoved(evicted, key, oldValue, newValue);
if (evicted) { if (evicted) {
@ -27,22 +26,22 @@ public class MemoryAssetLoader {
} }
} }
}; };
private static final HashMap<String, WeakReference<Bitmap>> evictionCache = new HashMap<>(); private static final HashMap<String, WeakReference<ScaledBitmap>> evictionCache = new HashMap<>();
private static String constructKey(CachedAppAssetLoader.LoaderTuple tuple) { private static String constructKey(CachedAppAssetLoader.LoaderTuple tuple) {
return tuple.computer.uuid+"-"+tuple.app.getAppId(); return tuple.computer.uuid+"-"+tuple.app.getAppId();
} }
public Bitmap loadBitmapFromCache(CachedAppAssetLoader.LoaderTuple tuple) { public ScaledBitmap loadBitmapFromCache(CachedAppAssetLoader.LoaderTuple tuple) {
final String key = constructKey(tuple); final String key = constructKey(tuple);
Bitmap bmp = memoryCache.get(key); ScaledBitmap bmp = memoryCache.get(key);
if (bmp != null) { if (bmp != null) {
LimeLog.info("LRU cache hit for tuple: "+tuple); LimeLog.info("LRU cache hit for tuple: "+tuple);
return bmp; return bmp;
} }
WeakReference<Bitmap> bmpRef = evictionCache.get(key); WeakReference<ScaledBitmap> bmpRef = evictionCache.get(key);
if (bmpRef != null) { if (bmpRef != null) {
bmp = bmpRef.get(); bmp = bmpRef.get();
if (bmp != null) { if (bmp != null) {
@ -63,7 +62,7 @@ public class MemoryAssetLoader {
return null; return null;
} }
public void populateCache(CachedAppAssetLoader.LoaderTuple tuple, Bitmap bitmap) { public void populateCache(CachedAppAssetLoader.LoaderTuple tuple, ScaledBitmap bitmap) {
memoryCache.put(constructKey(tuple), bitmap); memoryCache.put(constructKey(tuple), bitmap);
} }

View File

@ -0,0 +1,18 @@
package com.limelight.grid.assets;
import android.graphics.Bitmap;
public class ScaledBitmap {
public int originalWidth;
public int originalHeight;
public Bitmap bitmap;
public ScaledBitmap() {}
public ScaledBitmap(int originalWidth, int originalHeight, Bitmap bitmap) {
this.originalWidth = originalWidth;
this.originalHeight = originalHeight;
this.bitmap = bitmap;
}
}