diff options
author | Anonymous <no-reply@google.com> | 2021-07-07 14:01:06 -0700 |
---|---|---|
committer | Jeff Davidson <jpd@google.com> | 2021-07-07 23:09:19 +0000 |
commit | 212e7004acfdce76c900fd97070e2e5e8476be20 (patch) | |
tree | cf5d56ccdb862fd9676c855f919408ef940bc019 /src/main/java/com/android/volley/toolbox/ImageLoader.java | |
parent | b47af415ba74754b442c1f9f3960b29537d07e6e (diff) | |
download | volley-212e7004acfdce76c900fd97070e2e5e8476be20.tar.gz |
Import of Volley from GitHub to AOSP.android-s-beta-5android-s-beta-4android-s-beta-3android-s-beta-5android-s-beta-4
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.java | 541 |
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(); - } -} |