Skip to content

Commit

Permalink
Allow users to specify default transition options in GlideBuilder.
Browse files Browse the repository at this point in the history
Fixes #2182.
  • Loading branch information
sjudd committed Aug 11, 2017
1 parent 7e1548b commit 0b99260
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 21 deletions.
7 changes: 5 additions & 2 deletions library/src/main/java/com/bumptech/glide/Glide.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
Expand Down Expand Up @@ -275,7 +276,8 @@ private static GeneratedAppGlideModule getAnnotationGeneratedGlideModules() {
RequestManagerRetriever requestManagerRetriever,
ConnectivityMonitorFactory connectivityMonitorFactory,
int logLevel,
RequestOptions defaultRequestOptions) {
RequestOptions defaultRequestOptions,
Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions) {
this.engine = engine;
this.bitmapPool = bitmapPool;
this.arrayPool = arrayPool;
Expand Down Expand Up @@ -374,7 +376,8 @@ private static GeneratedAppGlideModule getAnnotationGeneratedGlideModules() {
ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
glideContext =
new GlideContext(
context, registry, imageViewTargetFactory, defaultRequestOptions, engine, logLevel);
context, registry, imageViewTargetFactory, defaultRequestOptions,
defaultTransitionOptions, engine, logLevel);
}

/**
Expand Down
29 changes: 28 additions & 1 deletion library/src/main/java/com/bumptech/glide/GlideBuilder.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.bumptech.glide;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.ArrayMap;
import android.util.Log;
import com.bumptech.glide.load.DecodeFormat;
import com.bumptech.glide.load.engine.Engine;
Expand All @@ -20,11 +22,13 @@
import com.bumptech.glide.manager.RequestManagerRetriever;
import com.bumptech.glide.manager.RequestManagerRetriever.RequestManagerFactory;
import com.bumptech.glide.request.RequestOptions;
import java.util.Map;

/**
* A builder class for setting default structural classes for Glide to use.
*/
public final class GlideBuilder {
private final Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions = new ArrayMap<>();
private Engine engine;
private BitmapPool bitmapPool;
private ArrayPool arrayPool;
Expand Down Expand Up @@ -157,6 +161,28 @@ public GlideBuilder setDefaultRequestOptions(RequestOptions requestOptions) {
return this;
}

/**
* Sets the default {@link TransitionOptions} to use when starting a request that will load a
* resource with the given {@link Class}.
*
* <p>It's preferable but not required for the requested resource class to match the resource
* class applied here as long as the resource class applied here is assignable from the requested
* resource class. For example you can set a default transition for
* {@link android.graphics.drawable.Drawable} and that default transition will be used if you
* subsequently start requests for specific {@link android.graphics.drawable.Drawable} types like
* {@link com.bumptech.glide.load.resource.gif.GifDrawable} or
* {@link android.graphics.drawable.BitmapDrawable}. Specific types are always preferred so if you
* register a default transition for both {@link android.graphics.drawable.Drawable} and
* {@link android.graphics.drawable.BitmapDrawable} and then start a request for
* {@link android.graphics.drawable.BitmapDrawable}s, the transition you registered for
* {@link android.graphics.drawable.BitmapDrawable}s will be used.
*/
public <T> GlideBuilder setDefaultTransitionOptions(
@NonNull Class<T> clazz, @Nullable TransitionOptions<?, T> options) {
defaultTransitionOptions.put(clazz, options);
return this;
}

/**
* Sets the {@link com.bumptech.glide.load.DecodeFormat} that will be the default format for all
* the default decoders that can change the {@link android.graphics.Bitmap.Config} of the {@link
Expand Down Expand Up @@ -314,6 +340,7 @@ public Glide build(Context context) {
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock());
defaultRequestOptions.lock(),
defaultTransitionOptions);
}
}
29 changes: 28 additions & 1 deletion library/src/main/java/com/bumptech/glide/GlideContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,42 @@
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;
import android.widget.ImageView;
import com.bumptech.glide.load.engine.Engine;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.ImageViewTargetFactory;
import com.bumptech.glide.request.target.Target;
import java.util.Map;
import java.util.Map.Entry;

/**
* Global context for all loads in Glide containing and exposing the various registries and classes
* required to load resources.
*/
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public class GlideContext extends ContextWrapper {
@VisibleForTesting
static final TransitionOptions<?, ?> DEFAULT_TRANSITION_OPTIONS =
new GenericTransitionOptions<Object>();
private final Handler mainHandler;
private final Registry registry;
private final ImageViewTargetFactory imageViewTargetFactory;
private final RequestOptions defaultRequestOptions;
private final Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions;
private final Engine engine;
private final int logLevel;

public GlideContext(Context context, Registry registry,
ImageViewTargetFactory imageViewTargetFactory, RequestOptions defaultRequestOptions,
Engine engine, int logLevel) {
Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions, Engine engine,
int logLevel) {
super(context.getApplicationContext());
this.registry = registry;
this.imageViewTargetFactory = imageViewTargetFactory;
this.defaultRequestOptions = defaultRequestOptions;
this.defaultTransitionOptions = defaultTransitionOptions;
this.engine = engine;
this.logLevel = logLevel;

Expand All @@ -42,6 +52,23 @@ public RequestOptions getDefaultRequestOptions() {
return defaultRequestOptions;
}

@SuppressWarnings("unchecked")
@NonNull
public <T> TransitionOptions<?, T> getDefaultTransitionOptions(Class<T> transcodeClass) {
TransitionOptions<?, ?> result = defaultTransitionOptions.get(transcodeClass);
if (result == null) {
for (Entry<Class<?>, TransitionOptions<?, ?>> value : defaultTransitionOptions.entrySet()) {
if (value.getKey().isAssignableFrom(transcodeClass)) {
result = value.getValue();
}
}
}
if (result == null) {
result = DEFAULT_TRANSITION_OPTIONS;
}
return (TransitionOptions<?, T>) result;
}

public <X> Target<X> buildImageViewTarget(ImageView imageView, Class<X> transcodeClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
}
Expand Down
15 changes: 10 additions & 5 deletions library/src/main/java/com/bumptech/glide/RequestBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@
* {@link com.bumptech.glide.request.target.Target}.
*/
public class RequestBuilder<TranscodeType> implements Cloneable {
private static final TransitionOptions<?, ?> DEFAULT_ANIMATION_OPTIONS =
new GenericTransitionOptions<Object>();
// Used in generated subclasses
protected static final RequestOptions DOWNLOAD_ONLY_OPTIONS =
new RequestOptions().diskCacheStrategy(DiskCacheStrategy.DATA).priority(Priority.LOW)
Expand All @@ -46,16 +44,18 @@ public class RequestBuilder<TranscodeType> implements Cloneable {
private final Glide glide;

@NonNull protected RequestOptions requestOptions;

@NonNull
@SuppressWarnings("unchecked")
private TransitionOptions<?, ? super TranscodeType> transitionOptions =
(TransitionOptions<?, ? super TranscodeType>) DEFAULT_ANIMATION_OPTIONS;
private TransitionOptions<?, ? super TranscodeType> transitionOptions;

@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<TranscodeType> requestListener;
@Nullable private RequestBuilder<TranscodeType> thumbnailBuilder;
@Nullable private Float thumbSizeMultiplier;
private boolean isDefaultTransitionOptionsSet = true;
private boolean isModelSet;
private boolean isThumbnailBuilt;

Expand All @@ -66,6 +66,7 @@ protected RequestBuilder(Glide glide, RequestManager requestManager,
this.context = glide.getGlideContext();
this.transcodeClass = transcodeClass;
this.defaultRequestOptions = requestManager.getDefaultRequestOptions();
this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass);
this.requestOptions = defaultRequestOptions;
}

Expand Down Expand Up @@ -106,6 +107,7 @@ protected RequestOptions getMutableOptions() {
public RequestBuilder<TranscodeType> transition(
@NonNull TransitionOptions<?, ? super TranscodeType> transitionOptions) {
this.transitionOptions = Preconditions.checkNotNull(transitionOptions);
isDefaultTransitionOptionsSet = false;
return this;
}

Expand Down Expand Up @@ -589,7 +591,10 @@ private Request buildRequestRecursive(Target<TranscodeType> target,

TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions =
thumbnailBuilder.transitionOptions;
if (DEFAULT_ANIMATION_OPTIONS.equals(thumbTransitionOptions)) {

// Apply our transition by default to thumbnail requests but avoid overriding custom options
// that may have been applied on the thumbnail request explicitly.
if (thumbnailBuilder.isDefaultTransitionOptionsSet) {
thumbTransitionOptions = transitionOptions;
}

Expand Down
13 changes: 8 additions & 5 deletions library/src/main/java/com/bumptech/glide/RequestManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import android.support.annotation.Nullable;
import android.view.View;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import com.bumptech.glide.load.resource.gif.GifDrawable;
import com.bumptech.glide.manager.ConnectivityMonitor;
import com.bumptech.glide.manager.ConnectivityMonitorFactory;
Expand Down Expand Up @@ -294,8 +293,7 @@ public void onDestroy() {
* @return A new request builder for loading a {@link android.graphics.Bitmap}
*/
public RequestBuilder<Bitmap> asBitmap() {
return as(Bitmap.class).transition(new GenericTransitionOptions<Bitmap>())
.apply(DECODE_TYPE_BITMAP);
return as(Bitmap.class).apply(DECODE_TYPE_BITMAP);
}

/**
Expand All @@ -312,7 +310,7 @@ public RequestBuilder<Bitmap> asBitmap() {
* {@link com.bumptech.glide.load.resource.gif.GifDrawable}.
*/
public RequestBuilder<GifDrawable> asGif() {
return as(GifDrawable.class).transition(new DrawableTransitionOptions()).apply(DECODE_TYPE_GIF);
return as(GifDrawable.class).apply(DECODE_TYPE_GIF);
}

/**
Expand All @@ -326,7 +324,7 @@ public RequestBuilder<GifDrawable> asGif() {
* @return A new request builder for loading a {@link Drawable}.
*/
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class).transition(new DrawableTransitionOptions());
return as(Drawable.class);
}

/**
Expand Down Expand Up @@ -460,6 +458,11 @@ RequestOptions getDefaultRequestOptions() {
return requestOptions;
}

@NonNull
<T> TransitionOptions<?, T> getDefaultTransitionOptions(Class<T> transcodeClass) {
return glide.getGlideContext().getDefaultTransitionOptions(transcodeClass);
}

@Override
public String toString() {
return super.toString() + "{tracker=" + requestTracker + ", treeNode=" + treeNode + "}";
Expand Down
71 changes: 71 additions & 0 deletions library/src/test/java/com/bumptech/glide/GlideContextTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.bumptech.glide;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;

import android.app.Application;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.Log;
import com.bumptech.glide.load.engine.Engine;
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import com.bumptech.glide.load.resource.gif.GifDrawable;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.ImageViewTargetFactory;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;

@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public final class GlideContextTest {
private Map<Class<?>, TransitionOptions<?, ?>> transitionOptions;
private GlideContext context;

@Before
public void setUp() {
Application app = RuntimeEnvironment.application;

transitionOptions = new HashMap<>();
context = new GlideContext(app, new Registry(),
new ImageViewTargetFactory(), new RequestOptions(),
transitionOptions, mock(Engine.class), Log.DEBUG);
}

@Test
public void getDefaultTransitionOptions_withNoOptionsRegistered_returnsDefaultOptions() {
assertThat(context.getDefaultTransitionOptions(Object.class))
.isEqualTo(GlideContext.DEFAULT_TRANSITION_OPTIONS);
}

@Test
public void getDefaultTransitionOptions_withNonMatchingOptionRegistered_returnsDefaultOptions() {
transitionOptions.put(Bitmap.class, new GenericTransitionOptions<>());
assertThat(context.getDefaultTransitionOptions(Drawable.class))
.isEqualTo(GlideContext.DEFAULT_TRANSITION_OPTIONS);
}

@Test
public void getDefaultTransitionOptions_withMatchingOptionsRegistered_returnsMatchingOptions() {
GenericTransitionOptions<Object> expected = new GenericTransitionOptions<>();
transitionOptions.put(Bitmap.class, expected);
assertThat(context.getDefaultTransitionOptions(Bitmap.class))
.isEqualTo(expected);
}

@Test
public void getDefaultTransitionOptions_withSuperClassRegistered_returnsSuperClassOptions() {
DrawableTransitionOptions expected = new DrawableTransitionOptions();
transitionOptions.put(Drawable.class, expected);
assertThat(context.getDefaultTransitionOptions(BitmapDrawable.class))
.isEqualTo(expected);
assertThat(context.getDefaultTransitionOptions(GifDrawable.class))
.isEqualTo(expected);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.bumptech.glide;

import static com.bumptech.glide.tests.BackgroundUtil.testInBackground;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -115,7 +116,9 @@ private RequestBuilder<Object> getNullModelRequest() {
.thenReturn(mock(Target.class));
when(glideContext.getDefaultRequestOptions()).thenReturn(new RequestOptions());
when(requestManager.getDefaultRequestOptions())
.thenReturn((RequestOptions) new RequestOptions());
.thenReturn(new RequestOptions());
when(requestManager.getDefaultTransitionOptions(any(Class.class)))
.thenReturn(new GenericTransitionOptions<>());
return new RequestBuilder<>(glide, requestManager, Object.class)
.load((Object) null);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.bumptech.glide.samples.flickr;

import static com.bumptech.glide.GenericTransitionOptions.withNoTransition;

import android.content.Intent;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
Expand Down Expand Up @@ -65,15 +63,13 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,

fullRequest = GlideApp.with(this)
.asDrawable()
.centerCrop()
.transition(withNoTransition());
.centerCrop();

thumbnailRequest = GlideApp.with(this)
.asDrawable()
.diskCacheStrategy(DiskCacheStrategy.DATA)
.centerCrop()
.override(Api.SQUARE_THUMB_SIZE)
.transition(withNoTransition());
.override(Api.SQUARE_THUMB_SIZE);

preloadRequest =
thumbnail ? thumbnailRequest.clone().priority(Priority.HIGH) : fullRequest;
Expand Down

0 comments on commit 0b99260

Please sign in to comment.