Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.bumptech.glide.RequestBuilder Maven / Gradle / Ivy
Go to download
A fast and efficient image loading library for Android focused on smooth scrolling.
package com.bumptech.glide;
import static com.bumptech.glide.request.RequestOptions.signatureOf;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.widget.ImageView;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.FutureTarget;
import com.bumptech.glide.request.Request;
import com.bumptech.glide.request.RequestCoordinator;
import com.bumptech.glide.request.RequestFutureTarget;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.SingleRequest;
import com.bumptech.glide.request.ThumbnailRequestCoordinator;
import com.bumptech.glide.request.target.PreloadTarget;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.signature.ApplicationVersionSignature;
import com.bumptech.glide.signature.ObjectKey;
import com.bumptech.glide.util.Preconditions;
import com.bumptech.glide.util.Util;
import java.io.File;
import java.net.URL;
import java.util.UUID;
/**
* A generic class that can handle setting options and staring loads for generic resource types.
*
* @param The type of resource that will be delivered to the
* {@link com.bumptech.glide.request.target.Target}.
*/
public class RequestBuilder implements Cloneable {
private static final TransitionOptions, ?> DEFAULT_ANIMATION_OPTIONS =
new GenericTransitionOptions();
// Used in generated subclasses
protected static final RequestOptions DOWNLOAD_ONLY_OPTIONS =
new RequestOptions().diskCacheStrategy(DiskCacheStrategy.DATA).priority(Priority.LOW)
.skipMemoryCache(true);
private final GlideContext context;
private final RequestManager requestManager;
private final Class transcodeClass;
private final RequestOptions defaultRequestOptions;
private final Glide glide;
@NonNull protected RequestOptions requestOptions;
@SuppressWarnings("unchecked")
private TransitionOptions, ? super TranscodeType> transitionOptions =
(TransitionOptions, ? super TranscodeType>) DEFAULT_ANIMATION_OPTIONS;
@Nullable private Object model;
// model may occasionally be null, so to enforce that load() was called, put a boolean rather
// than relying on model not to be null.
@Nullable private RequestListener requestListener;
@Nullable private RequestBuilder thumbnailBuilder;
@Nullable private Float thumbSizeMultiplier;
private boolean isModelSet;
private boolean isThumbnailBuilt;
protected RequestBuilder(Glide glide, RequestManager requestManager,
Class transcodeClass) {
this.glide = glide;
this.requestManager = requestManager;
this.context = glide.getGlideContext();
this.transcodeClass = transcodeClass;
this.defaultRequestOptions = requestManager.getDefaultRequestOptions();
this.requestOptions = defaultRequestOptions;
}
protected RequestBuilder(Class transcodeClass, RequestBuilder> other) {
this(other.glide, other.requestManager, transcodeClass);
model = other.model;
isModelSet = other.isModelSet;
requestOptions = other.requestOptions;
}
/**
* Applies the given options to the request, options set or unset in the given options will
* replace those previously set in options in this class.
*
* @see RequestOptions#apply(RequestOptions)
* @return This request builder.
*/
public RequestBuilder apply(@NonNull RequestOptions requestOptions) {
Preconditions.checkNotNull(requestOptions);
this.requestOptions = getMutableOptions().apply(requestOptions);
return this;
}
protected RequestOptions getMutableOptions() {
return defaultRequestOptions == this.requestOptions
? this.requestOptions.clone() : this.requestOptions;
}
/**
* Sets the {@link TransitionOptions} to use to transition from the placeholder or thumbnail when
* this load completes.
*
* The given {@link TransitionOptions} will replace any {@link TransitionOptions} set
* previously.
*
* @return This request builder.
*/
public RequestBuilder transition(
@NonNull TransitionOptions, ? super TranscodeType> transitionOptions) {
this.transitionOptions = Preconditions.checkNotNull(transitionOptions);
return this;
}
/**
* Sets a RequestBuilder listener to monitor the resource load. It's best to create a single
* instance of an exception handler per type of request (usually activity/fragment) rather than
* pass one in per request to avoid some redundant object allocation.
*
* @param requestListener The request listener to use.
* @return This request builder.
*/
@SuppressWarnings("unchecked")
public RequestBuilder listener(
@Nullable RequestListener requestListener) {
this.requestListener = requestListener;
return this;
}
/**
* Loads and displays the resource retrieved by the given thumbnail request if it finishes before
* this request. Best used for loading thumbnail resources that are smaller and will be loaded
* more quickly than the full size resource. There are no guarantees about the order in which the
* requests will actually finish. However, if the thumb request completes after the full request,
* the thumb resource will never replace the full resource.
*
* @param thumbnailRequest The request to use to load the thumbnail.
* @return This request builder.
* @see #thumbnail(float)
*
* Recursive calls to thumbnail are supported.
*/
@SuppressWarnings("unchecked")
public RequestBuilder thumbnail(
@Nullable RequestBuilder thumbnailRequest) {
this.thumbnailBuilder = thumbnailRequest;
return this;
}
/**
* Loads a resource in an identical manner to this request except with the dimensions of the
* target multiplied by the given size multiplier. If the thumbnail load completes before the full
* size load, the thumbnail will be shown. If the thumbnail load completes after the full size
* load, the thumbnail will not be shown.
*
* Note - The thumbnail resource will be smaller than the size requested so the target (or
* {@link ImageView}) must be able to scale the thumbnail appropriately. See
* {@link android.widget.ImageView.ScaleType}.
*
* Almost all options will be copied from the original load, including the {@link
* com.bumptech.glide.load.model.ModelLoader}, {@link com.bumptech.glide.load.ResourceDecoder},
* and {@link com.bumptech.glide.load.Transformation}s. However,
* {@link com.bumptech.glide.request.RequestOptions#placeholder(int)} and
* {@link com.bumptech.glide.request.RequestOptions#error(int)}, and
* {@link #listener(RequestListener)} will only be used on the full size load and will not be
* copied for the thumbnail load.
*
* Recursive calls to thumbnail are supported.
*
* @param sizeMultiplier The multiplier to apply to the {@link Target}'s dimensions when loading
* the thumbnail.
* @return This request builder.
*/
@SuppressWarnings("unchecked")
public RequestBuilder thumbnail(float sizeMultiplier) {
if (sizeMultiplier < 0f || sizeMultiplier > 1f) {
throw new IllegalArgumentException("sizeMultiplier must be between 0 and 1");
}
this.thumbSizeMultiplier = sizeMultiplier;
return this;
}
/**
* Sets the specific model to load data for.
*
* This method must be called at least once before
* {@link #into(com.bumptech.glide.request.target.Target)} is called.
*
* @param model The model to load data for, or null.
* @return This request builder.
*/
@SuppressWarnings("unchecked")
public RequestBuilder load(@Nullable Object model) {
return loadGeneric(model);
}
private RequestBuilder loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
/**
* Returns a request builder to load the given {@link java.lang.String}. signature.
*
* Note - this method caches data using only the given String as the cache key. If the data is
* a Uri outside of your control, or you otherwise expect the data represented by the given String
* to change without the String identifier changing, Consider using
* {@link com.bumptech.glide.request.RequestOptions#signature(com.bumptech.glide.load.Key)} to
* mixin a signature you create that identifies the data currently at the given String that will
* invalidate the cache if that data changes. Alternatively, using
* {@link com.bumptech.glide.load.engine.DiskCacheStrategy#NONE} and/or
* {@link com.bumptech.glide.request.RequestOptions#skipMemoryCache(boolean)} may be
* appropriate.
*
*
* @see #load(Object)
*
* @param string A file path, or a uri or url handled by
* {@link com.bumptech.glide.load.model.UriLoader}.
*/
public RequestBuilder load(@Nullable String string) {
return loadGeneric(string);
}
/**
* Returns a request builder to load the given {@link Uri}.
*
* Note - this method caches data at Uris using only the Uri itself as the cache key. The data
* represented by Uris from some content providers may change without the Uri changing, which
* means using this method can lead to displaying stale data. Consider using
* {@link com.bumptech.glide.request.RequestOptions#signature(com.bumptech.glide.load.Key)} to
* mixin a signature you create based on the data at the given Uri that will invalidate the cache
* if that data changes. Alternatively, using
* {@link com.bumptech.glide.load.engine.DiskCacheStrategy#NONE} and/or
* {@link com.bumptech.glide.request.RequestOptions#skipMemoryCache(boolean)} may be
* appropriate.
*
* @see #load(Object)
*
* @param uri The Uri representing the image. Must be of a type handled by
* {@link com.bumptech.glide.load.model.UriLoader}.
*/
public RequestBuilder load(@Nullable Uri uri) {
return loadGeneric(uri);
}
/**
* Returns a request builder to load the given {@link File}.
*
* Note - this method caches data for Files using only the file path itself as the cache key.
* The data in the File can change so using this method can lead to displaying stale data. If you
* expect the data in the File to change, Consider using
* {@link com.bumptech.glide.request.RequestOptions#signature(com.bumptech.glide.load.Key)}
* to mixin a signature you create that identifies the data currently in the File that will
* invalidate the cache if that data changes. Alternatively, using
* {@link com.bumptech.glide.load.engine.DiskCacheStrategy#NONE} and/or
* {@link com.bumptech.glide.request.RequestOptions#skipMemoryCache(boolean)} may be
* appropriate.
*
*
* @see #load(Object)
*
* @param file The File containing the image
*/
public RequestBuilder load(@Nullable File file) {
return loadGeneric(file);
}
/**
* Returns a request builder to load the given resource id. Returns a request builder that uses
* the {@link com.bumptech.glide.load.model.ModelLoaderFactory} currently registered or
* {@link Integer} to load the image represented by the given {@link Integer} resource id.
* Defaults to {@link com.bumptech.glide.load.model.ResourceLoader} to load resource id models.
*
* By default this method adds a version code based signature to the cache key used to cache
* this resource in Glide. This signature is sufficient to guarantee that end users will see the
* most up to date versions of your Drawables, but during development if you do not increment your
* version code before each install and you replace a Drawable with different data without
* changing the Drawable name, you may see inconsistent cached data. To get around this, consider
* using {@link com.bumptech.glide.load.engine.DiskCacheStrategy#NONE} via
* {@link RequestOptions#diskCacheStrategy(com.bumptech.glide.load.engine.DiskCacheStrategy)}
* during development, and re-enabling the default
* {@link com.bumptech.glide.load.engine.DiskCacheStrategy#RESOURCE} for release builds.
*
* @see #load(Integer)
* @see com.bumptech.glide.signature.ApplicationVersionSignature
*/
public RequestBuilder load(@Nullable Integer resourceId) {
return loadGeneric(resourceId).apply(signatureOf(ApplicationVersionSignature.obtain(context)));
}
/**
* Returns a request builder to load the given {@link URL}.
*
* @param url The URL representing the image.
* @see #load(Object)
* @deprecated The {@link java.net.URL} class has a number of
* performance problems and should generally be avoided when possible. Prefer
* {@link #load(android.net.Uri)} or {@link #load(String)}.
*/
@Deprecated
public RequestBuilder load(@Nullable URL url) {
return loadGeneric(url);
}
/**
* Returns a request to load the given byte array.
*
* Note - by default loads for bytes are not cached in either the memory or the disk cache.
*
*
* @param model the data to load.
* @see #load(Object)
*/
public RequestBuilder load(@Nullable byte[] model) {
return loadGeneric(model).apply(signatureOf(new ObjectKey(UUID.randomUUID().toString()))
.diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true /*skipMemoryCache*/));
}
/**
* Returns a copy of this request builder with all of the options put so far on this builder.
*
* This method returns a "deep" copy in that all non-immutable arguments are copied such that
* changes to one builder will not affect the other builder. However, in addition to immutable
* arguments, the current model is not copied copied so changes to the model will affect both
* builders.
*/
@SuppressWarnings("unchecked")
@Override
public RequestBuilder clone() {
try {
RequestBuilder result = (RequestBuilder) super.clone();
result.requestOptions = result.requestOptions.clone();
result.transitionOptions = result.transitionOptions.clone();
return result;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
/**
* Set the target the resource will be loaded into.
*
* @param target The target to load the resource into.
* @return The given target.
* @see RequestManager#clear(Target)
*/
public > Y into(@NonNull Y target) {
Util.assertMainThread();
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
Request previous = target.getRequest();
if (previous != null) {
requestManager.clear(target);
}
requestOptions.lock();
Request request = buildRequest(target);
target.setRequest(request);
requestManager.track(target, request);
return target;
}
/**
* Sets the {@link ImageView} the resource will be loaded into, cancels any existing loads into
* the view, and frees any resources Glide may have previously loaded into the view so they may be
* reused.
*
* @see RequestManager#clear(Target)
*
* @param view The view to cancel previous loads for and load the new resource into.
* @return The
* {@link com.bumptech.glide.request.target.Target} used to wrap the given {@link ImageView}.
*/
public Target into(ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
if (requestOptions.isLocked()) {
requestOptions = requestOptions.clone();
}
switch (view.getScaleType()) {
case CENTER_CROP:
requestOptions.optionalCenterCrop();
break;
case CENTER_INSIDE:
requestOptions.optionalCenterInside();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
requestOptions.optionalFitCenter();
break;
case FIT_XY:
requestOptions.optionalCenterInside();
break;
case CENTER:
case MATRIX:
default:
// Do nothing.
}
}
return into(context.buildImageViewTarget(view, transcodeClass));
}
/**
* Returns a future that can be used to do a blocking get on a background thread.
*
* @param width The desired width in pixels, or {@link Target#SIZE_ORIGINAL}. This will be
* overridden by
* {@link com.bumptech.glide.request.RequestOptions#override(int, int)} if
* previously called.
* @param height The desired height in pixels, or {@link Target#SIZE_ORIGINAL}. This will be
* overridden by
* {@link com.bumptech.glide.request.RequestOptions#override(int, int)}} if
* previously called).
* @see RequestManager#clear(Target)
*
* @deprecated Use {@link #submit(int, int)} instead.
*/
@Deprecated
public FutureTarget into(int width, int height) {
return submit(width, height);
}
/**
* Returns a future that can be used to do a blocking get on a background thread.
*
* This method defaults to {@link Target#SIZE_ORIGINAL} for the width and the height. However,
* since the width and height will be overridden by values passed to {@link
* RequestOptions#override(int, int)}, this method can be used whenever {@link RequestOptions}
* with override values are applied, or whenever you want to retrieve the image in its original
* size.
*
* @see #submit(int, int)
* @see #into(Target)
*/
public FutureTarget submit() {
return submit(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
}
/**
* Returns a future that can be used to do a blocking get on a background thread.
*
* @param width The desired width in pixels, or {@link Target#SIZE_ORIGINAL}. This will be
* overridden by
* {@link com.bumptech.glide.request.RequestOptions#override(int, int)} if
* previously called.
* @param height The desired height in pixels, or {@link Target#SIZE_ORIGINAL}. This will be
* overridden by
* {@link com.bumptech.glide.request.RequestOptions#override(int, int)}} if
* previously called).
*/
public FutureTarget submit(int width, int height) {
final RequestFutureTarget target =
new RequestFutureTarget<>(context.getMainHandler(), width, height);
if (Util.isOnBackgroundThread()) {
context.getMainHandler().post(new Runnable() {
@Override
public void run() {
if (!target.isCancelled()) {
into(target);
}
}
});
} else {
into(target);
}
return target;
}
/**
* Preloads the resource into the cache using the given width and height.
*
* Pre-loading is useful for making sure that resources you are going to to want in the near
* future are available quickly.
*
* @param width The desired width in pixels, or {@link Target#SIZE_ORIGINAL}. This will be
* overridden by
* {@link com.bumptech.glide.request.RequestOptions#override(int, int)} if
* previously called.
* @param height The desired height in pixels, or {@link Target#SIZE_ORIGINAL}. This will be
* overridden by
* {@link com.bumptech.glide.request.RequestOptions#override(int, int)}} if
* previously called).
* @return A {@link Target} that can be used to cancel the load via
* {@link RequestManager#clear(Target)}.
* @see com.bumptech.glide.ListPreloader
*/
public Target preload(int width, int height) {
final PreloadTarget target = PreloadTarget.obtain(requestManager, width, height);
return into(target);
}
/**
* Preloads the resource into the cache using {@link Target#SIZE_ORIGINAL} as the target width and
* height. Equivalent to calling {@link #preload(int, int)} with {@link Target#SIZE_ORIGINAL} as
* the width and height.
*
* @return A {@link Target} that can be used to cancel the load via
* {@link RequestManager#clear(Target)}
* @see #preload(int, int)
*/
public Target preload() {
return preload(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
}
/**
* Loads the original unmodified data into the cache and calls the given Target with the cache
* File.
*
* @param target The Target that will receive the cache File when the load completes
* @param The type of Target.
* @return The given Target.
*
* @deprecated Use {@link RequestManager#downloadOnly()} and {@link #into(Target)}.
*/
@Deprecated
public > Y downloadOnly(Y target) {
return getDownloadOnlyRequest().into(target);
}
/**
* Loads the original unmodified data into the cache and returns a
* {@link java.util.concurrent.Future} that can be used to retrieve the cache File containing the
* data.
*
* @param width The width in pixels to use to fetch the data.
* @param height The height in pixels to use to fetch the data.
* @return A {@link java.util.concurrent.Future} that can be used to retrieve the cache File
* containing the data.
*
* @deprecated Use {@link RequestManager#downloadOnly()} and {@link #into(int, int)}.
*/
@Deprecated
public FutureTarget downloadOnly(int width, int height) {
return getDownloadOnlyRequest().submit(width, height);
}
protected RequestBuilder getDownloadOnlyRequest() {
return new RequestBuilder<>(File.class, this).apply(DOWNLOAD_ONLY_OPTIONS);
}
private Priority getThumbnailPriority(Priority current) {
switch (current) {
case LOW:
return Priority.NORMAL;
case NORMAL:
return Priority.HIGH;
case HIGH:
case IMMEDIATE:
return Priority.IMMEDIATE;
default:
throw new IllegalArgumentException("unknown priority: " + requestOptions.getPriority());
}
}
private Request buildRequest(Target target) {
return buildRequestRecursive(target, null, transitionOptions, requestOptions.getPriority(),
requestOptions.getOverrideWidth(), requestOptions.getOverrideHeight());
}
private Request buildRequestRecursive(Target target,
@Nullable ThumbnailRequestCoordinator parentCoordinator,
TransitionOptions, ? super TranscodeType> transitionOptions,
Priority priority, int overrideWidth, int overrideHeight) {
if (thumbnailBuilder != null) {
// Recursive case: contains a potentially recursive thumbnail request builder.
if (isThumbnailBuilt) {
throw new IllegalStateException("You cannot use a request as both the main request and a "
+ "thumbnail, consider using clone() on the request(s) passed to thumbnail()");
}
TransitionOptions, ? super TranscodeType> thumbTransitionOptions =
thumbnailBuilder.transitionOptions;
if (DEFAULT_ANIMATION_OPTIONS.equals(thumbTransitionOptions)) {
thumbTransitionOptions = transitionOptions;
}
Priority thumbPriority = thumbnailBuilder.requestOptions.isPrioritySet()
? thumbnailBuilder.requestOptions.getPriority() : getThumbnailPriority(priority);
int thumbOverrideWidth = thumbnailBuilder.requestOptions.getOverrideWidth();
int thumbOverrideHeight = thumbnailBuilder.requestOptions.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !thumbnailBuilder.requestOptions.isValidOverride()) {
thumbOverrideWidth = requestOptions.getOverrideWidth();
thumbOverrideHeight = requestOptions.getOverrideHeight();
}
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest = obtainRequest(target, requestOptions, coordinator,
transitionOptions, priority, overrideWidth, overrideHeight);
isThumbnailBuilt = true;
// Recursively generate thumbnail requests.
Request thumbRequest = thumbnailBuilder.buildRequestRecursive(target, coordinator,
thumbTransitionOptions, thumbPriority, thumbOverrideWidth, thumbOverrideHeight);
isThumbnailBuilt = false;
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
} else if (thumbSizeMultiplier != null) {
// Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest = obtainRequest(target, requestOptions, coordinator, transitionOptions,
priority, overrideWidth, overrideHeight);
RequestOptions thumbnailOptions = requestOptions.clone()
.sizeMultiplier(thumbSizeMultiplier);
Request thumbnailRequest = obtainRequest(target, thumbnailOptions, coordinator,
transitionOptions, getThumbnailPriority(priority), overrideWidth, overrideHeight);
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else {
// Base case: no thumbnail.
return obtainRequest(target, requestOptions, parentCoordinator, transitionOptions, priority,
overrideWidth, overrideHeight);
}
}
private Request obtainRequest(Target target,
RequestOptions requestOptions, RequestCoordinator requestCoordinator,
TransitionOptions, ? super TranscodeType> transitionOptions, Priority priority,
int overrideWidth, int overrideHeight) {
requestOptions.lock();
return SingleRequest.obtain(
context,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
requestListener,
requestCoordinator,
context.getEngine(),
transitionOptions.getTransitionFactory());
}
}