diff options
author | Anonymous <no-reply@google.com> | 2018-10-11 11:02:44 -0700 |
---|---|---|
committer | Jeff Davidson <jpd@google.com> | 2018-10-11 11:50:43 -0700 |
commit | d998d6e2d201bd26bab6f7624ccfa2242b58a05e (patch) | |
tree | 26a0438ea15ce7651d1c54cb99f13e2d8d1951dd /src/main | |
parent | c409124cab8fa87dab8a3e42ce34844f5a4fa7ea (diff) | |
download | volley-oreo-mr1-1.2-iot-release.tar.gz |
Import of Volley from GitHub to AOSP.android-o-mr1-iot-release-smart-display-r3oreo-mr1-1.2-iot-release
- 321174452380acd5caa7c19aac99cb95a2ed0ff6 Add a default image bitmap and an error image bitmap. (#2... by Ammar Aijazi <aaijazi@users.noreply.github.com>
- cb5d331761c4785b325acc7ff5caf8f41e932c69 Bump Volley to 1.2.0-SNAPSHOT. by Jeff Davidson <jpd@google.com>
- c31351334868a17cb79ab5b067d798bc80e343a3 Fix the build. by Jeff Davidson <jpd@google.com>
- 99d8ed84ddf653cb5f61a9ad63e5a3ced799d9ce Reduce cache churn from large entries. by Jeff Davidson <jpd@google.com>
- 6b7b3a2df79506269a0730a095849c5a87fc9cbb Enforce disk size limit more strictly in DiskBasedCache. by Jeff Davidson <jpd@google.com>
- 64481a321b9e57c78f22c7df53732e03f530933a Don't drop batched responses when new requests complete. ... by Jeff Davidson <jpd236@cornell.edu>
- 4e60e9d2ac2f2c81661a7f0d1bcbc72c190059c2 Bump version to 1.1.2 after final 1.1.1 release by Jeff Davidson <jpd@google.com>
- d1a3d5388c79ff1a6fdb904daeff9b39d0bb7d26 Delete Android.mk (#204) by Jeff Davidson <jpd236@cornell.edu>
GitOrigin-RevId: 321174452380acd5caa7c19aac99cb95a2ed0ff6
Change-Id: I433459689ad2fe1bf40e8ff30d196d948ef73f81
Diffstat (limited to 'src/main')
3 files changed, 102 insertions, 25 deletions
diff --git a/src/main/java/com/android/volley/toolbox/DiskBasedCache.java b/src/main/java/com/android/volley/toolbox/DiskBasedCache.java index c49588f..75c217f 100644 --- a/src/main/java/com/android/volley/toolbox/DiskBasedCache.java +++ b/src/main/java/com/android/volley/toolbox/DiskBasedCache.java @@ -65,7 +65,7 @@ public class DiskBasedCache implements Cache { private static final int DEFAULT_DISK_USAGE_BYTES = 5 * 1024 * 1024; /** High water mark percentage for the cache */ - private static final float HYSTERESIS_FACTOR = 0.9f; + @VisibleForTesting static final float HYSTERESIS_FACTOR = 0.9f; /** Magic number for current version of cache file format. */ private static final int CACHE_MAGIC = 0x20150306; @@ -74,7 +74,9 @@ public class DiskBasedCache implements Cache { * Constructs an instance of the DiskBasedCache at the specified directory. * * @param rootDirectory The root directory of the cache. - * @param maxCacheSizeInBytes The maximum size of the cache in bytes. + * @param maxCacheSizeInBytes The maximum size of the cache in bytes. Note that the cache may + * briefly exceed this size on disk when writing a new entry that pushes it over the limit + * until the ensuing pruning completes. */ public DiskBasedCache(File rootDirectory, int maxCacheSizeInBytes) { mRootDirectory = rootDirectory; @@ -166,8 +168,6 @@ public class DiskBasedCache implements Cache { new BufferedInputStream(createInputStream(file)), entrySize); try { CacheHeader entry = CacheHeader.readHeader(cis); - // NOTE: When this entry was put, its size was recorded as data.length, but - // when the entry is initialized below, its size is recorded as file.length() entry.size = entrySize; putEntry(entry.key, entry); } finally { @@ -203,7 +203,14 @@ public class DiskBasedCache implements Cache { /** Puts the entry with the specified key into the cache. */ @Override public synchronized void put(String key, Entry entry) { - pruneIfNeeded(entry.data.length); + // If adding this entry would trigger a prune, but pruning would cause the new entry to be + // deleted, then skip writing the entry in the first place, as this is just churn. + // Note that we don't include the cache header overhead in this calculation for simplicity, + // so putting entries which are just below the threshold may still cause this churn. + if (mTotalSize + entry.data.length > mMaxCacheSizeInBytes + && entry.data.length > mMaxCacheSizeInBytes * HYSTERESIS_FACTOR) { + return; + } File file = getFileForKey(key); try { BufferedOutputStream fos = new BufferedOutputStream(createOutputStream(file)); @@ -216,7 +223,9 @@ public class DiskBasedCache implements Cache { } fos.write(entry.data); fos.close(); + e.size = file.length(); putEntry(key, e); + pruneIfNeeded(); return; } catch (IOException e) { } @@ -256,13 +265,9 @@ public class DiskBasedCache implements Cache { return new File(mRootDirectory, getFilenameForKey(key)); } - /** - * Prunes the cache to fit the amount of bytes specified. - * - * @param neededSpace The amount of bytes we are trying to fit into the cache. - */ - private void pruneIfNeeded(int neededSpace) { - if ((mTotalSize + neededSpace) < mMaxCacheSizeInBytes) { + /** Prunes the cache to fit the maximum size. */ + private void pruneIfNeeded() { + if (mTotalSize < mMaxCacheSizeInBytes) { return; } if (VolleyLog.DEBUG) { @@ -288,7 +293,7 @@ public class DiskBasedCache implements Cache { iterator.remove(); prunedFiles++; - if ((mTotalSize + neededSpace) < mMaxCacheSizeInBytes * HYSTERESIS_FACTOR) { + if (mTotalSize < mMaxCacheSizeInBytes * HYSTERESIS_FACTOR) { break; } } @@ -331,7 +336,7 @@ public class DiskBasedCache implements Cache { * @param length number of bytes to read * @throws IOException if fails to read all bytes */ - // VisibleForTesting + @VisibleForTesting static byte[] streamToBytes(CountingInputStream cis, long length) throws IOException { long maxLength = cis.bytesRemaining(); // Length cannot be negative or greater than bytes remaining, and must not overflow int. @@ -343,20 +348,26 @@ public class DiskBasedCache implements Cache { return bytes; } - // VisibleForTesting + @VisibleForTesting InputStream createInputStream(File file) throws FileNotFoundException { return new FileInputStream(file); } - // VisibleForTesting + @VisibleForTesting OutputStream createOutputStream(File file) throws FileNotFoundException { return new FileOutputStream(file); } /** Handles holding onto the cache headers for an entry. */ - // VisibleForTesting + @VisibleForTesting static class CacheHeader { - /** The size of the data identified by this CacheHeader. (This is not serialized to disk. */ + /** + * The size of the data identified by this CacheHeader on disk (both header and data). + * + * <p>Must be set by the caller after it has been calculated. + * + * <p>This is not serialized to disk. + */ long size; /** The key that identifies the cache entry. */ @@ -389,7 +400,7 @@ public class DiskBasedCache implements Cache { long softTtl, List<Header> allResponseHeaders) { this.key = key; - this.etag = ("".equals(etag)) ? null : etag; + this.etag = "".equals(etag) ? null : etag; this.serverDate = serverDate; this.lastModified = lastModified; this.ttl = ttl; @@ -412,7 +423,6 @@ public class DiskBasedCache implements Cache { entry.ttl, entry.softTtl, getAllResponseHeaders(entry)); - size = entry.data.length; } private static List<Header> getAllResponseHeaders(Entry entry) { diff --git a/src/main/java/com/android/volley/toolbox/ImageLoader.java b/src/main/java/com/android/volley/toolbox/ImageLoader.java index 076c212..270935f 100644 --- a/src/main/java/com/android/volley/toolbox/ImageLoader.java +++ b/src/main/java/com/android/volley/toolbox/ImageLoader.java @@ -239,8 +239,11 @@ public class ImageLoader { // Update the caller to let them know that they should use the default bitmap. imageListener.onResponse(imageContainer, true); - // Check to see if a request is already in-flight. + // Check to see if a request is already in-flight or completed but pending batch delivery. BatchedImageRequest request = mInFlightRequests.get(cacheKey); + if (request == null) { + request = mBatchedResponses.get(cacheKey); + } if (request != null) { // If it is, add this request to the list of listeners. request.addContainer(imageContainer); diff --git a/src/main/java/com/android/volley/toolbox/NetworkImageView.java b/src/main/java/com/android/volley/toolbox/NetworkImageView.java index a490a79..6ad1e49 100644 --- a/src/main/java/com/android/volley/toolbox/NetworkImageView.java +++ b/src/main/java/com/android/volley/toolbox/NetworkImageView.java @@ -14,7 +14,9 @@ package com.android.volley.toolbox; import android.content.Context; +import android.graphics.Bitmap; import android.support.annotation.MainThread; +import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.AttributeSet; import android.view.ViewGroup.LayoutParams; @@ -28,12 +30,30 @@ public class NetworkImageView extends ImageView { /** The URL of the network image to load */ private String mUrl; - /** Resource ID of the image to be used as a placeholder until the network image is loaded. */ + /** + * Resource ID of the image to be used as a placeholder until the network image is loaded. Won't + * be set at the same time as mDefaultImageBitmap. + */ private int mDefaultImageId; - /** Resource ID of the image to be used if the network response fails. */ + /** + * Bitmap of the image to be used as a placeholder until the network image is loaded. Won't be + * set at the same time as mDefaultImageId. + */ + @Nullable Bitmap mDefaultImageBitmap; + + /** + * Resource ID of the image to be used if the network response fails. Won't be set at the same + * time as mErrorImageBitmap. + */ private int mErrorImageId; + /** + * Bitmap of the image to be used if the network response fails. Won't be set at the same time + * as mErrorImageId. + */ + @Nullable private Bitmap mErrorImageBitmap; + /** Local copy of the ImageLoader. */ private ImageLoader mImageLoader; @@ -57,8 +77,10 @@ public class NetworkImageView extends ImageView { * immediately either set the cached image (if available) or the default image specified by * {@link NetworkImageView#setDefaultImageResId(int)} on the view. * - * <p>NOTE: If applicable, {@link NetworkImageView#setDefaultImageResId(int)} and {@link - * NetworkImageView#setErrorImageResId(int)} should be called prior to calling this function. + * <p>NOTE: If applicable, {@link NetworkImageView#setDefaultImageResId(int)} or {@link + * NetworkImageView#setDefaultImageBitmap} and {@link NetworkImageView#setErrorImageResId(int)} + * or {@link NetworkImageView#setErrorImageBitmap(Bitmap)} should be called prior to calling + * this function. * * <p>Must be called from the main thread. * @@ -77,20 +99,56 @@ public class NetworkImageView extends ImageView { /** * Sets the default image resource ID to be used for this view until the attempt to load it * completes. + * + * <p>Cannot be called with {@link NetworkImageView#setDefaultImageBitmap}. */ public void setDefaultImageResId(int defaultImage) { + if (mDefaultImageBitmap != null) { + throw new IllegalArgumentException("Can't have a default image resource ID and bitmap"); + } mDefaultImageId = defaultImage; } /** + * Sets the default image bitmap to be used for this view until the attempt to load it + * completes. + * + * <p>Cannot be called with {@link NetworkImageView#setDefaultImageResId}. + */ + public void setDefaultImageBitmap(Bitmap defaultImage) { + if (mDefaultImageId != 0) { + throw new IllegalArgumentException("Can't have a default image resource ID and bitmap"); + } + mDefaultImageBitmap = defaultImage; + } + + /** * Sets the error image resource ID to be used for this view in the event that the image * requested fails to load. + * + * <p>Cannot be called with {@link NetworkImageView#setErrorImageBitmap}. */ public void setErrorImageResId(int errorImage) { + if (mErrorImageBitmap != null) { + throw new IllegalArgumentException("Can't have an error image resource ID and bitmap"); + } mErrorImageId = errorImage; } /** + * Sets the error image bitmap to be used for this view in the event that the image requested + * fails to load. + * + * <p>Cannot be called with {@link NetworkImageView#setErrorImageResId}. + */ + public void setErrorImageBitmap(Bitmap errorImage) { + if (mErrorImageId != 0) { + throw new IllegalArgumentException("Can't have an error image resource ID and bitmap"); + } + mErrorImageBitmap = errorImage; + } + + /** * Loads the image for the view if it isn't already loaded. * * @param isInLayoutPass True if this was invoked from a layout pass, false otherwise. @@ -152,6 +210,8 @@ public class NetworkImageView extends ImageView { public void onErrorResponse(VolleyError error) { if (mErrorImageId != 0) { setImageResource(mErrorImageId); + } else if (mErrorImageBitmap != null) { + setImageBitmap(mErrorImageBitmap); } } @@ -180,6 +240,8 @@ public class NetworkImageView extends ImageView { setImageBitmap(response.getBitmap()); } else if (mDefaultImageId != 0) { setImageResource(mDefaultImageId); + } else if (mDefaultImageBitmap != null) { + setImageBitmap(mDefaultImageBitmap); } } }, @@ -191,6 +253,8 @@ public class NetworkImageView extends ImageView { private void setDefaultImageOrNull() { if (mDefaultImageId != 0) { setImageResource(mDefaultImageId); + } else if (mDefaultImageBitmap != null) { + setImageBitmap(mDefaultImageBitmap); } else { setImageBitmap(null); } |