Skip to content

Commit

Permalink
Add global/activity/fragment scoped RequestListener API to Glide.
Browse files Browse the repository at this point in the history
After this change, callers will be able to add one or more
RequestListeners either to all requests started with Glide, or to all
requests started within a particular Activity or Fragment.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=209947609
  • Loading branch information
sjudd committed Aug 30, 2018
1 parent a9e1ae2 commit 37127f0
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 8 deletions.
19 changes: 14 additions & 5 deletions library/src/main/java/com/bumptech/glide/Glide.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import android.view.View;
import com.bumptech.glide.gifdecoder.GifDecoder;
import com.bumptech.glide.load.DecodeFormat;
import com.bumptech.glide.load.ImageHeaderParser;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.data.InputStreamRewinder;
import com.bumptech.glide.load.engine.Engine;
Expand Down Expand Up @@ -76,6 +77,7 @@
import com.bumptech.glide.manager.ConnectivityMonitorFactory;
import com.bumptech.glide.manager.RequestManagerRetriever;
import com.bumptech.glide.module.ManifestParser;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.ImageViewTargetFactory;
import com.bumptech.glide.request.target.Target;
Expand Down Expand Up @@ -319,7 +321,8 @@ private static void throwIncorrectGlideModule(Exception e) {
@NonNull ConnectivityMonitorFactory connectivityMonitorFactory,
int logLevel,
@NonNull RequestOptions defaultRequestOptions,
@NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions) {
@NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions,
@NonNull List<RequestListener<Object>> defaultRequestListeners) {
this.engine = engine;
this.bitmapPool = bitmapPool;
this.arrayPool = arrayPool;
Expand All @@ -342,10 +345,15 @@ private static void throwIncorrectGlideModule(Exception e) {
}
registry.register(new DefaultImageHeaderParser());

Downsampler downsampler = new Downsampler(registry.getImageHeaderParsers(),
resources.getDisplayMetrics(), bitmapPool, arrayPool);
List<ImageHeaderParser> imageHeaderParsers = registry.getImageHeaderParsers();
Downsampler downsampler =
new Downsampler(
imageHeaderParsers,
resources.getDisplayMetrics(),
bitmapPool,
arrayPool);
ByteBufferGifDecoder byteBufferGifDecoder =
new ByteBufferGifDecoder(context, registry.getImageHeaderParsers(), bitmapPool, arrayPool);
new ByteBufferGifDecoder(context, imageHeaderParsers, bitmapPool, arrayPool);
ResourceDecoder<ParcelFileDescriptor, Bitmap> parcelFileDescriptorVideoDecoder =
VideoDecoder.parcel(bitmapPool);
ByteBufferBitmapDecoder byteBufferBitmapDecoder = new ByteBufferBitmapDecoder(downsampler);
Expand Down Expand Up @@ -409,7 +417,7 @@ Registry.BUCKET_BITMAP, Bitmap.class, Bitmap.class, new UnitBitmapDecoder())
Registry.BUCKET_GIF,
InputStream.class,
GifDrawable.class,
new StreamGifDecoder(registry.getImageHeaderParsers(), byteBufferGifDecoder, arrayPool))
new StreamGifDecoder(imageHeaderParsers, byteBufferGifDecoder, arrayPool))
.append(Registry.BUCKET_GIF, ByteBuffer.class, GifDrawable.class, byteBufferGifDecoder)
.append(GifDrawable.class, new GifDrawableEncoder())
/* GIF Frames */
Expand Down Expand Up @@ -512,6 +520,7 @@ Uri.class, Bitmap.class, new ResourceBitmapDecoder(resourceDrawableDecoder, bitm
imageViewTargetFactory,
defaultRequestOptions,
defaultTransitionOptions,
defaultRequestListeners,
engine,
logLevel);
}
Expand Down
43 changes: 42 additions & 1 deletion library/src/main/java/com/bumptech/glide/GlideBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
import android.support.annotation.Nullable;
import android.support.v4.util.ArrayMap;
import android.util.Log;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.Engine;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.load.engine.bitmap_recycle.ArrayPool;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPoolAdapter;
Expand All @@ -22,8 +24,12 @@
import com.bumptech.glide.manager.DefaultConnectivityMonitorFactory;
import com.bumptech.glide.manager.RequestManagerRetriever;
import com.bumptech.glide.manager.RequestManagerRetriever.RequestManagerFactory;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.Target;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
Expand All @@ -46,6 +52,8 @@ public final class GlideBuilder {
private RequestManagerFactory requestManagerFactory;
private GlideExecutor animationExecutor;
private boolean isActiveResourceRetentionAllowed;
@Nullable
private List<RequestListener<Object>> defaultRequestListeners;

/**
* Sets the {@link com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool} implementation to use
Expand Down Expand Up @@ -372,6 +380,32 @@ public GlideBuilder setIsActiveResourceRetentionAllowed(
return this;
}

/**
* Adds a global {@link RequestListener} that will be added to every request started with Glide.
*
* <p>Multiple {@link RequestListener}s can be added here, in {@link RequestManager} scopes or
* to individual {@link RequestBuilder}s. {@link RequestListener}s are called in the order they're
* added. Even if an earlier {@link RequestListener} returns {@code true} from
* {@link RequestListener#onLoadFailed(GlideException, Object, Target, boolean)} or
* {@link RequestListener#onResourceReady(Object, Object, Target, DataSource, boolean)}, it will
* not prevent subsequent {@link RequestListener}s from being called.
*
* <p>Because Glide requests can be started for any number of individual resource types, any
* listener added here has to accept any generic resource type in
* {@link RequestListener#onResourceReady(Object, Object, Target, DataSource, boolean)}. If you
* must base the behavior of the listener on the resource type, you will need to use
* {@code instanceof} to do so. It's not safe to cast resource types without first checking
* with {@code instanceof}.
*/
@NonNull
public GlideBuilder addGlobalRequestListener(@NonNull RequestListener<Object> listener) {
if (defaultRequestListeners == null) {
defaultRequestListeners = new ArrayList<>();
}
defaultRequestListeners.add(listener);
return this;
}

void setRequestManagerFactory(@Nullable RequestManagerFactory factory) {
this.requestManagerFactory = factory;
}
Expand Down Expand Up @@ -437,6 +471,12 @@ Glide build(@NonNull Context context) {
isActiveResourceRetentionAllowed);
}

if (defaultRequestListeners == null) {
defaultRequestListeners = Collections.emptyList();
} else {
defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
}

RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);

Expand All @@ -450,6 +490,7 @@ Glide build(@NonNull Context context) {
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock(),
defaultTransitionOptions);
defaultTransitionOptions,
defaultRequestListeners);
}
}
9 changes: 9 additions & 0 deletions library/src/main/java/com/bumptech/glide/GlideContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
import android.widget.ImageView;
import com.bumptech.glide.load.engine.Engine;
import com.bumptech.glide.load.engine.bitmap_recycle.ArrayPool;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.ImageViewTargetFactory;
import com.bumptech.glide.request.target.ViewTarget;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

Expand All @@ -28,6 +30,7 @@ public class GlideContext extends ContextWrapper {
private final Registry registry;
private final ImageViewTargetFactory imageViewTargetFactory;
private final RequestOptions defaultRequestOptions;
private final List<RequestListener<Object>> defaultRequestListeners;
private final Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions;
private final Engine engine;
private final int logLevel;
Expand All @@ -39,20 +42,26 @@ public GlideContext(
@NonNull ImageViewTargetFactory imageViewTargetFactory,
@NonNull RequestOptions defaultRequestOptions,
@NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions,
@NonNull List<RequestListener<Object>> defaultRequestListeners,
@NonNull Engine engine,
int logLevel) {
super(context.getApplicationContext());
this.arrayPool = arrayPool;
this.registry = registry;
this.imageViewTargetFactory = imageViewTargetFactory;
this.defaultRequestOptions = defaultRequestOptions;
this.defaultRequestListeners = defaultRequestListeners;
this.defaultTransitionOptions = defaultTransitionOptions;
this.engine = engine;
this.logLevel = logLevel;

mainHandler = new Handler(Looper.getMainLooper());
}

public List<RequestListener<Object>> getDefaultRequestListeners() {
return defaultRequestListeners;
}

public RequestOptions getDefaultRequestOptions() {
return defaultRequestOptions;
}
Expand Down
21 changes: 19 additions & 2 deletions library/src/main/java/com/bumptech/glide/RequestBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static com.bumptech.glide.request.RequestOptions.signatureOf;
import static com.bumptech.glide.request.RequestOptions.skipMemoryCacheOf;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
Expand Down Expand Up @@ -76,8 +77,12 @@ public class RequestBuilder<TranscodeType> implements Cloneable,
private boolean isModelSet;
private boolean isThumbnailBuilt;

protected RequestBuilder(Glide glide, RequestManager requestManager,
Class<TranscodeType> transcodeClass, Context context) {
@SuppressLint("CheckResult")
protected RequestBuilder(
@NonNull Glide glide,
RequestManager requestManager,
Class<TranscodeType> transcodeClass,
Context context) {
this.glide = glide;
this.requestManager = requestManager;
this.transcodeClass = transcodeClass;
Expand All @@ -86,6 +91,8 @@ protected RequestBuilder(Glide glide, RequestManager requestManager,
this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass);
this.requestOptions = defaultRequestOptions;
this.glideContext = glide.getGlideContext();

initRequestListeners(requestManager.getDefaultRequestListeners());
}

protected RequestBuilder(Class<TranscodeType> transcodeClass, RequestBuilder<?> other) {
Expand All @@ -95,6 +102,16 @@ protected RequestBuilder(Class<TranscodeType> transcodeClass, RequestBuilder<?>
requestOptions = other.requestOptions;
}

// Casting from Object to a specific type is always safe.
@SuppressWarnings("unchecked")
// addListener always returns the same instance.
@SuppressLint("CheckResult")
private void initRequestListeners(List<RequestListener<Object>> requestListeners) {
for (RequestListener<Object> listener : requestListeners) {
addListener((RequestListener<TranscodeType>) listener);
}
}

/**
* Applies the given options to the request.
*
Expand Down
38 changes: 38 additions & 0 deletions library/src/main/java/com/bumptech/glide/RequestManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
import android.support.annotation.Nullable;
import android.support.annotation.RawRes;
import android.view.View;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.load.resource.gif.GifDrawable;
import com.bumptech.glide.manager.ConnectivityMonitor;
import com.bumptech.glide.manager.ConnectivityMonitorFactory;
Expand All @@ -26,6 +28,7 @@
import com.bumptech.glide.manager.RequestTracker;
import com.bumptech.glide.manager.TargetTracker;
import com.bumptech.glide.request.Request;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.target.ViewTarget;
Expand All @@ -34,6 +37,8 @@
import com.bumptech.glide.util.Util;
import java.io.File;
import java.net.URL;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
* A class for managing and starting requests for Glide. Can use activity, fragment and connectivity
Expand Down Expand Up @@ -69,6 +74,10 @@ public void run() {
};
private final Handler mainHandler = new Handler(Looper.getMainLooper());
private final ConnectivityMonitor connectivityMonitor;
// Adding default listeners should be much less common than starting new requests. We want
// some way of making sure that requests don't mutate our listeners without creating a new copy of
// the list each time a request is started.
private final CopyOnWriteArrayList<RequestListener<Object>> defaultRequestListeners;

private RequestOptions requestOptions;

Expand Down Expand Up @@ -115,6 +124,8 @@ public RequestManager(
}
lifecycle.addListener(connectivityMonitor);

defaultRequestListeners =
new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());

glide.registerRequestManager(this);
Expand Down Expand Up @@ -174,6 +185,29 @@ public RequestManager setDefaultRequestOptions(@NonNull RequestOptions requestOp
return this;
}

/**
* Adds a default {@link RequestListener} that will be added to every request started with this
* {@link RequestManager}.
*
* <p>Multiple {@link RequestListener}s can be added here, in {@link RequestManager} scopes or
* to individual {@link RequestBuilder}s. {@link RequestListener}s are called in the order they're
* added. Even if an earlier {@link RequestListener} returns {@code true} from
* {@link RequestListener#onLoadFailed(GlideException, Object, Target, boolean)} or
* {@link RequestListener#onResourceReady(Object, Object, Target, DataSource, boolean)}, it will
* not prevent subsequent {@link RequestListener}s from being called.
*
* <p>Because Glide requests can be started for any number of individual resource types, any
* listener added here has to accept any generic resource type in
* {@link RequestListener#onResourceReady(Object, Object, Target, DataSource, boolean)}. If you
* must base the behavior of the listener on the resource type, you will need to use
* {@code instanceof} to do so. It's not safe to cast resource types without first checking
* with {@code instanceof}.
*/
public RequestManager addDefaultRequestListener(RequestListener<Object> requestListener) {
defaultRequestListeners.add(requestListener);
return this;
}

/**
* Returns true if loads for this {@link RequestManager} are currently paused.
*
Expand Down Expand Up @@ -614,6 +648,10 @@ void track(@NonNull Target<?> target, @NonNull Request request) {
requestTracker.runRequest(request);
}

List<RequestListener<Object>> getDefaultRequestListeners() {
return defaultRequestListeners;
}

RequestOptions getDefaultRequestOptions() {
return requestOptions;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.bumptech.glide.load.resource.gif.GifDrawable;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.ImageViewTargetFactory;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
Expand Down Expand Up @@ -41,6 +42,7 @@ public void setUp() {
new ImageViewTargetFactory(),
new RequestOptions(),
transitionOptions,
/*defaultRequestListeners=*/ Collections.emptyList(),
mock(Engine.class),
Log.DEBUG);
}
Expand Down

0 comments on commit 37127f0

Please sign in to comment.