aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/android/volley/toolbox/ImageLoader.java
diff options
context:
space:
mode:
authorAnonymous <no-reply@google.com>2021-07-07 14:01:06 -0700
committerJeff Davidson <jpd@google.com>2021-07-07 23:09:19 +0000
commit212e7004acfdce76c900fd97070e2e5e8476be20 (patch)
treecf5d56ccdb862fd9676c855f919408ef940bc019 /src/main/java/com/android/volley/toolbox/ImageLoader.java
parentb47af415ba74754b442c1f9f3960b29537d07e6e (diff)
downloadvolley-212e7004acfdce76c900fd97070e2e5e8476be20.tar.gz
Android.bp has been updated to account for the new source directory structure. - 0dc50bcfd021c204a9e6c9e7e6befbdfa1027247 Refactor Volley into a multi-module project. (#418) by Jeff Davidson <jpd@google.com> - 763c86b0bc9f66a8bb499f6a8b7fd3bdc87621a8 Remove new constructors from JsonRequests which are break... by Jeff Davidson <jpd@google.com> - 8d1b1a59e7cd1b1d3c6d8686f8831cea08f80d1f Add @NonNull annotations to Volley (#413) by Kamal Faraj <kfaraj.dev@gmail.com> - 5ba41f8670413973f587e435598f9f1724fa26e9 Allow sending any JSON with JsonArrayRequest & JsonObject... by Paul Smith <paulsmithkc@gmail.com> - 784cdd755392a6080e5eb0bf94bd7bf4ea31cf17 Update SNAPSHOT version after 1.2.0 release by Jeff Davidson <jpd@google.com> - 0d6497bab417a5f78b3c8e03ea157ada0fbfbc5d Add developers stanza to Volley POM. (#400) by Jeff Davidson <jpd@google.com> - 36274bf515a699ae5a7fe3d321206d1b803226d8 API cleanup for Async Volley stack ahead of 1.2.0 release... by Jeff Davidson <jpd@google.com> - 03f0144843fcf9ebafe512647c1c588975429452 Update environment variable name for snapshot pushes. (#3... by Jeff Davidson <jpd@google.com> - 3bd1975652687d2baa1b11a7f02b135edede8523 Publish SNAPSHOT builds to OSSRH instead of OJO. (#397) by Jeff Davidson <jpd@google.com> - 0e0c3d9cfa694f8f1400a9e9abc4bc11761fdb52 Invoke RetryPolicy#retry in the blocking executor. (#393) by Jeff Davidson <jpd@google.com> - b51831a48f06ad28f627c3624e5edb41598a2bf8 Use a consistent timebase when evaluating soft/hard TTLs.... by Jeff Davidson <jpd@google.com> - cd0839113b100f163df1ebd04ce6d5b9e36e9863 Migrate from Travis CI to GitHub Actions. (#381) by Jeff Davidson <jpd@google.com> - bdc0e393199ebf9e67c4e29e665252818eed4639 Clean up cache initialization in AsyncRequestQueue. (#380) by Jeff Davidson <jpd@google.com> - 1c0ade36edde15d02844b40351ab6f80c63b71b3 Actually allow applications to provide custom executors. by Jeff Davidson <jpd@google.com> GitOrigin-RevId: 0dc50bcfd021c204a9e6c9e7e6befbdfa1027247 Change-Id: I4b8e4098ad5c349cb83efc867273fac1d3582a34
Diffstat (limited to 'src/main/java/com/android/volley/toolbox/ImageLoader.java')
-rw-r--r--src/main/java/com/android/volley/toolbox/ImageLoader.java541
1 files changed, 0 insertions, 541 deletions
diff --git a/src/main/java/com/android/volley/toolbox/ImageLoader.java b/src/main/java/com/android/volley/toolbox/ImageLoader.java
deleted file mode 100644
index eece2cf..0000000
--- a/src/main/java/com/android/volley/toolbox/ImageLoader.java
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.volley.toolbox;
-
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.os.Handler;
-import android.os.Looper;
-import android.widget.ImageView;
-import android.widget.ImageView.ScaleType;
-import androidx.annotation.MainThread;
-import androidx.annotation.Nullable;
-import com.android.volley.Request;
-import com.android.volley.RequestQueue;
-import com.android.volley.Response.ErrorListener;
-import com.android.volley.Response.Listener;
-import com.android.volley.ResponseDelivery;
-import com.android.volley.VolleyError;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Helper that handles loading and caching images from remote URLs.
- *
- * <p>The simple way to use this class is to call {@link ImageLoader#get(String, ImageListener)} and
- * to pass in the default image listener provided by {@link ImageLoader#getImageListener(ImageView,
- * int, int)}. Note that all function calls to this class must be made from the main thread, and all
- * responses will be delivered to the main thread as well. Custom {@link ResponseDelivery}s which
- * don't use the main thread are not supported.
- */
-public class ImageLoader {
- /** RequestQueue for dispatching ImageRequests onto. */
- private final RequestQueue mRequestQueue;
-
- /** Amount of time to wait after first response arrives before delivering all responses. */
- private int mBatchResponseDelayMs = 100;
-
- /** The cache implementation to be used as an L1 cache before calling into volley. */
- private final ImageCache mCache;
-
- /**
- * HashMap of Cache keys -> BatchedImageRequest used to track in-flight requests so that we can
- * coalesce multiple requests to the same URL into a single network request.
- */
- private final HashMap<String, BatchedImageRequest> mInFlightRequests = new HashMap<>();
-
- /** HashMap of the currently pending responses (waiting to be delivered). */
- private final HashMap<String, BatchedImageRequest> mBatchedResponses = new HashMap<>();
-
- /** Handler to the main thread. */
- private final Handler mHandler = new Handler(Looper.getMainLooper());
-
- /** Runnable for in-flight response delivery. */
- private Runnable mRunnable;
-
- /**
- * Simple cache adapter interface. If provided to the ImageLoader, it will be used as an L1
- * cache before dispatch to Volley. Implementations must not block. Implementation with an
- * LruCache is recommended.
- */
- public interface ImageCache {
- @Nullable
- Bitmap getBitmap(String url);
-
- void putBitmap(String url, Bitmap bitmap);
- }
-
- /**
- * Constructs a new ImageLoader.
- *
- * @param queue The RequestQueue to use for making image requests.
- * @param imageCache The cache to use as an L1 cache.
- */
- public ImageLoader(RequestQueue queue, ImageCache imageCache) {
- mRequestQueue = queue;
- mCache = imageCache;
- }
-
- /**
- * The default implementation of ImageListener which handles basic functionality of showing a
- * default image until the network response is received, at which point it will switch to either
- * the actual image or the error image.
- *
- * @param view The imageView that the listener is associated with.
- * @param defaultImageResId Default image resource ID to use, or 0 if it doesn't exist.
- * @param errorImageResId Error image resource ID to use, or 0 if it doesn't exist.
- */
- public static ImageListener getImageListener(
- final ImageView view, final int defaultImageResId, final int errorImageResId) {
- return new ImageListener() {
- @Override
- public void onErrorResponse(VolleyError error) {
- if (errorImageResId != 0) {
- view.setImageResource(errorImageResId);
- }
- }
-
- @Override
- public void onResponse(ImageContainer response, boolean isImmediate) {
- if (response.getBitmap() != null) {
- view.setImageBitmap(response.getBitmap());
- } else if (defaultImageResId != 0) {
- view.setImageResource(defaultImageResId);
- }
- }
- };
- }
-
- /**
- * Interface for the response handlers on image requests.
- *
- * <p>The call flow is this: 1. Upon being attached to a request, onResponse(response, true)
- * will be invoked to reflect any cached data that was already available. If the data was
- * available, response.getBitmap() will be non-null.
- *
- * <p>2. After a network response returns, only one of the following cases will happen: -
- * onResponse(response, false) will be called if the image was loaded. or - onErrorResponse will
- * be called if there was an error loading the image.
- */
- public interface ImageListener extends ErrorListener {
- /**
- * Listens for non-error changes to the loading of the image request.
- *
- * @param response Holds all information pertaining to the request, as well as the bitmap
- * (if it is loaded).
- * @param isImmediate True if this was called during ImageLoader.get() variants. This can be
- * used to differentiate between a cached image loading and a network image loading in
- * order to, for example, run an animation to fade in network loaded images.
- */
- void onResponse(ImageContainer response, boolean isImmediate);
- }
-
- /**
- * Checks if the item is available in the cache.
- *
- * @param requestUrl The url of the remote image
- * @param maxWidth The maximum width of the returned image.
- * @param maxHeight The maximum height of the returned image.
- * @return True if the item exists in cache, false otherwise.
- */
- public boolean isCached(String requestUrl, int maxWidth, int maxHeight) {
- return isCached(requestUrl, maxWidth, maxHeight, ScaleType.CENTER_INSIDE);
- }
-
- /**
- * Checks if the item is available in the cache.
- *
- * <p>Must be called from the main thread.
- *
- * @param requestUrl The url of the remote image
- * @param maxWidth The maximum width of the returned image.
- * @param maxHeight The maximum height of the returned image.
- * @param scaleType The scaleType of the imageView.
- * @return True if the item exists in cache, false otherwise.
- */
- @MainThread
- public boolean isCached(String requestUrl, int maxWidth, int maxHeight, ScaleType scaleType) {
- Threads.throwIfNotOnMainThread();
-
- String cacheKey = getCacheKey(requestUrl, maxWidth, maxHeight, scaleType);
- return mCache.getBitmap(cacheKey) != null;
- }
-
- /**
- * Returns an ImageContainer for the requested URL.
- *
- * <p>The ImageContainer will contain either the specified default bitmap or the loaded bitmap.
- * If the default was returned, the {@link ImageLoader} will be invoked when the request is
- * fulfilled.
- *
- * @param requestUrl The URL of the image to be loaded.
- */
- public ImageContainer get(String requestUrl, final ImageListener listener) {
- return get(requestUrl, listener, /* maxWidth= */ 0, /* maxHeight= */ 0);
- }
-
- /**
- * Equivalent to calling {@link #get(String, ImageListener, int, int, ScaleType)} with {@code
- * Scaletype == ScaleType.CENTER_INSIDE}.
- */
- public ImageContainer get(
- String requestUrl, ImageListener imageListener, int maxWidth, int maxHeight) {
- return get(requestUrl, imageListener, maxWidth, maxHeight, ScaleType.CENTER_INSIDE);
- }
-
- /**
- * Issues a bitmap request with the given URL if that image is not available in the cache, and
- * returns a bitmap container that contains all of the data relating to the request (as well as
- * the default image if the requested image is not available).
- *
- * <p>Must be called from the main thread.
- *
- * @param requestUrl The url of the remote image
- * @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).
- */
- @MainThread
- public ImageContainer get(
- String requestUrl,
- ImageListener imageListener,
- int maxWidth,
- int maxHeight,
- ScaleType scaleType) {
-
- // only fulfill requests that were initiated from the main thread.
- Threads.throwIfNotOnMainThread();
-
- final String cacheKey = getCacheKey(requestUrl, maxWidth, maxHeight, scaleType);
-
- // Try to look up the request in the cache of remote images.
- Bitmap cachedBitmap = mCache.getBitmap(cacheKey);
- if (cachedBitmap != null) {
- // Return the cached bitmap.
- ImageContainer container =
- new ImageContainer(
- cachedBitmap, requestUrl, /* cacheKey= */ null, /* listener= */ null);
- imageListener.onResponse(container, true);
- return container;
- }
-
- // The bitmap did not exist in the cache, fetch it!
- ImageContainer imageContainer =
- new ImageContainer(null, requestUrl, cacheKey, imageListener);
-
- // 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 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);
- return imageContainer;
- }
-
- // The request is not already in flight. Send the new request to the network and
- // track it.
- Request<Bitmap> newRequest =
- makeImageRequest(requestUrl, maxWidth, maxHeight, scaleType, cacheKey);
-
- mRequestQueue.add(newRequest);
- mInFlightRequests.put(cacheKey, new BatchedImageRequest(newRequest, imageContainer));
- return imageContainer;
- }
-
- 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,
- scaleType,
- Config.RGB_565,
- new ErrorListener() {
- @Override
- public void onErrorResponse(VolleyError error) {
- onGetImageError(cacheKey, error);
- }
- });
- }
-
- /**
- * Sets the amount of time to wait after the first response arrives before delivering all
- * responses. Batching can be disabled entirely by passing in 0.
- *
- * @param newBatchedResponseDelayMs The time in milliseconds to wait.
- */
- public void setBatchedResponseDelay(int newBatchedResponseDelayMs) {
- mBatchResponseDelayMs = newBatchedResponseDelayMs;
- }
-
- /**
- * Handler for when an image was successfully loaded.
- *
- * @param cacheKey The cache key that is associated with the image request.
- * @param response The bitmap that was returned from the network.
- */
- protected void onGetImageSuccess(String cacheKey, Bitmap response) {
- // cache the image that was fetched.
- mCache.putBitmap(cacheKey, response);
-
- // remove the request from the list of in-flight requests.
- BatchedImageRequest request = mInFlightRequests.remove(cacheKey);
-
- if (request != null) {
- // Update the response bitmap.
- request.mResponseBitmap = response;
-
- // Send the batched response
- batchResponse(cacheKey, request);
- }
- }
-
- /**
- * Handler for when an image failed to load.
- *
- * @param cacheKey The cache key that is associated with the image request.
- */
- protected void onGetImageError(String cacheKey, VolleyError error) {
- // Notify the requesters that something failed via a null result.
- // Remove this request from the list of in-flight requests.
- BatchedImageRequest request = mInFlightRequests.remove(cacheKey);
-
- if (request != null) {
- // Set the error for this request
- request.setError(error);
-
- // Send the batched response
- batchResponse(cacheKey, request);
- }
- }
-
- /** Container object for all of the data surrounding an image request. */
- public class ImageContainer {
- /**
- * The most relevant bitmap for the container. If the image was in cache, the Holder to use
- * for the final bitmap (the one that pairs to the requested URL).
- */
- private Bitmap mBitmap;
-
- private final ImageListener mListener;
-
- /** The cache key that was associated with the request */
- private final String mCacheKey;
-
- /** The request URL that was specified */
- private final String mRequestUrl;
-
- /**
- * Constructs a BitmapContainer object.
- *
- * @param bitmap The final bitmap (if it exists).
- * @param requestUrl The requested URL for this container.
- * @param cacheKey The cache key that identifies the requested URL for this container.
- */
- public ImageContainer(
- Bitmap bitmap, String requestUrl, String cacheKey, ImageListener listener) {
- mBitmap = bitmap;
- mRequestUrl = requestUrl;
- mCacheKey = cacheKey;
- mListener = listener;
- }
-
- /**
- * Releases interest in the in-flight request (and cancels it if no one else is listening).
- *
- * <p>Must be called from the main thread.
- */
- @MainThread
- public void cancelRequest() {
- Threads.throwIfNotOnMainThread();
-
- if (mListener == null) {
- return;
- }
-
- BatchedImageRequest request = mInFlightRequests.get(mCacheKey);
- if (request != null) {
- boolean canceled = request.removeContainerAndCancelIfNecessary(this);
- if (canceled) {
- mInFlightRequests.remove(mCacheKey);
- }
- } else {
- // check to see if it is already batched for delivery.
- request = mBatchedResponses.get(mCacheKey);
- if (request != null) {
- request.removeContainerAndCancelIfNecessary(this);
- if (request.mContainers.size() == 0) {
- mBatchedResponses.remove(mCacheKey);
- }
- }
- }
- }
-
- /**
- * Returns the bitmap associated with the request URL if it has been loaded, null otherwise.
- */
- public Bitmap getBitmap() {
- return mBitmap;
- }
-
- /** Returns the requested URL for this container. */
- public String getRequestUrl() {
- return mRequestUrl;
- }
- }
-
- /**
- * Wrapper class used to map a Request to the set of active ImageContainer objects that are
- * interested in its results.
- */
- private static class BatchedImageRequest {
- /** The request being tracked */
- private final Request<?> mRequest;
-
- /** The result of the request being tracked by this item */
- private Bitmap mResponseBitmap;
-
- /** Error if one occurred for this response */
- private VolleyError mError;
-
- /** List of all of the active ImageContainers that are interested in the request */
- private final List<ImageContainer> mContainers = new ArrayList<>();
-
- /**
- * Constructs a new BatchedImageRequest object
- *
- * @param request The request being tracked
- * @param container The ImageContainer of the person who initiated the request.
- */
- public BatchedImageRequest(Request<?> request, ImageContainer container) {
- mRequest = request;
- mContainers.add(container);
- }
-
- /** Set the error for this response */
- public void setError(VolleyError error) {
- mError = error;
- }
-
- /** Get the error for this response */
- public VolleyError getError() {
- return mError;
- }
-
- /**
- * Adds another ImageContainer to the list of those interested in the results of the
- * request.
- */
- public void addContainer(ImageContainer container) {
- mContainers.add(container);
- }
-
- /**
- * Detaches the bitmap container from the request and cancels the request if no one is left
- * listening.
- *
- * @param container The container to remove from the list
- * @return True if the request was canceled, false otherwise.
- */
- public boolean removeContainerAndCancelIfNecessary(ImageContainer container) {
- mContainers.remove(container);
- if (mContainers.size() == 0) {
- mRequest.cancel();
- return true;
- }
- return false;
- }
- }
-
- /**
- * Starts the runnable for batched delivery of responses if it is not already started.
- *
- * @param cacheKey The cacheKey of the response being delivered.
- * @param request The BatchedImageRequest to be delivered.
- */
- private void batchResponse(String cacheKey, BatchedImageRequest request) {
- mBatchedResponses.put(cacheKey, request);
- // If we don't already have a batch delivery runnable in flight, make a new one.
- // Note that this will be used to deliver responses to all callers in mBatchedResponses.
- if (mRunnable == null) {
- mRunnable =
- new Runnable() {
- @Override
- public void run() {
- for (BatchedImageRequest bir : mBatchedResponses.values()) {
- for (ImageContainer container : bir.mContainers) {
- // If one of the callers in the batched request canceled the
- // request
- // after the response was received but before it was delivered,
- // skip them.
- if (container.mListener == null) {
- continue;
- }
- if (bir.getError() == null) {
- container.mBitmap = bir.mResponseBitmap;
- container.mListener.onResponse(container, false);
- } else {
- container.mListener.onErrorResponse(bir.getError());
- }
- }
- }
- mBatchedResponses.clear();
- mRunnable = null;
- }
- };
- // Post the runnable.
- mHandler.postDelayed(mRunnable, mBatchResponseDelayMs);
- }
- }
-
- /**
- * Creates a cache key for use with the L1 cache.
- *
- * @param url The URL of the request.
- * @param maxWidth The max-width of the output.
- * @param maxHeight The max-height of the output.
- * @param scaleType The scaleType of the imageView.
- */
- private static String getCacheKey(
- String url, int maxWidth, int maxHeight, ScaleType scaleType) {
- return new StringBuilder(url.length() + 12)
- .append("#W")
- .append(maxWidth)
- .append("#H")
- .append(maxHeight)
- .append("#S")
- .append(scaleType.ordinal())
- .append(url)
- .toString();
- }
-}