From 7663c214e44964529173ca48e0faf3e588f5a386 Mon Sep 17 00:00:00 2001 From: Sam Judd Date: Sun, 22 Oct 2017 18:51:33 -0700 Subject: [PATCH] Add support for passing through Bitmaps and Drawables. --- .../main/java/com/bumptech/glide/Glide.java | 7 +++ .../com/bumptech/glide/RequestBuilder.java | 56 ++++++++++++++++++- .../resource/bitmap/UnitBitmapDecoder.java | 30 ++++++++++ .../drawable/DrawableResourceImpl.java | 45 +++++++++++++++ .../drawable/ResourceDrawableDecoder.java | 39 +------------ .../drawable/UnitDrawableDecoder.java | 32 +++++++++++ .../java/com/bumptech/glide/GlideTest.java | 37 ++++++++++++ 7 files changed, 207 insertions(+), 39 deletions(-) create mode 100644 library/src/main/java/com/bumptech/glide/load/resource/bitmap/UnitBitmapDecoder.java create mode 100644 library/src/main/java/com/bumptech/glide/load/resource/drawable/DrawableResourceImpl.java create mode 100644 library/src/main/java/com/bumptech/glide/load/resource/drawable/UnitDrawableDecoder.java diff --git a/library/src/main/java/com/bumptech/glide/Glide.java b/library/src/main/java/com/bumptech/glide/Glide.java index fe46eb058..1c27d2991 100644 --- a/library/src/main/java/com/bumptech/glide/Glide.java +++ b/library/src/main/java/com/bumptech/glide/Glide.java @@ -54,9 +54,11 @@ import com.bumptech.glide.load.resource.bitmap.DefaultImageHeaderParser; import com.bumptech.glide.load.resource.bitmap.Downsampler; import com.bumptech.glide.load.resource.bitmap.ResourceBitmapDecoder; import com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder; +import com.bumptech.glide.load.resource.bitmap.UnitBitmapDecoder; import com.bumptech.glide.load.resource.bitmap.VideoBitmapDecoder; import com.bumptech.glide.load.resource.bytes.ByteBufferRewinder; import com.bumptech.glide.load.resource.drawable.ResourceDrawableDecoder; +import com.bumptech.glide.load.resource.drawable.UnitDrawableDecoder; import com.bumptech.glide.load.resource.file.FileDecoder; import com.bumptech.glide.load.resource.gif.ByteBufferGifDecoder; import com.bumptech.glide.load.resource.gif.GifDrawable; @@ -321,6 +323,9 @@ public class Glide implements ComponentCallbacks2 { .append(Registry.BUCKET_BITMAP, InputStream.class, Bitmap.class, streamBitmapDecoder) .append( Registry.BUCKET_BITMAP, ParcelFileDescriptor.class, Bitmap.class, videoBitmapDecoder) + .append( + Registry.BUCKET_BITMAP, Bitmap.class, Bitmap.class, new UnitBitmapDecoder(bitmapPool)) + .append(Bitmap.class, Bitmap.class, UnitModelLoader.Factory.getInstance()) .append(Bitmap.class, bitmapEncoder) /* BitmapDrawables */ .append( @@ -406,6 +411,8 @@ public class Glide implements ComponentCallbacks2 { .append(byte[].class, ByteBuffer.class, new ByteArrayLoader.ByteBufferFactory()) .append(byte[].class, InputStream.class, new ByteArrayLoader.StreamFactory()) .append(Uri.class, Uri.class, UnitModelLoader.Factory.getInstance()) + .append(Drawable.class, Drawable.class, UnitModelLoader.Factory.getInstance()) + .append(Drawable.class, Drawable.class, new UnitDrawableDecoder(bitmapPool)) /* Transcoders */ .register( Bitmap.class, diff --git a/library/src/main/java/com/bumptech/glide/RequestBuilder.java b/library/src/main/java/com/bumptech/glide/RequestBuilder.java index 38d9ce454..026634e91 100644 --- a/library/src/main/java/com/bumptech/glide/RequestBuilder.java +++ b/library/src/main/java/com/bumptech/glide/RequestBuilder.java @@ -1,8 +1,11 @@ package com.bumptech.glide; +import static com.bumptech.glide.request.RequestOptions.diskCacheStrategyOf; import static com.bumptech.glide.request.RequestOptions.signatureOf; import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.support.annotation.CheckResult; import android.support.annotation.DrawableRes; @@ -317,7 +320,58 @@ public class RequestBuilder implements Cloneable { } /** - * Returns a request builder to load the given {@link java.lang.String}. signature. + * Returns a request builder to load the given {@link Bitmap}. + * + *

{@link Bitmap}s provided to this method become owned by Glide. The {@link Bitmap} may be + * recycled or re-used at any time. If you do not own the Bitmap or you need to continue to use + * the {@link Bitmap} after passing it in to Glide, consider passing a copy of the {@link Bitmap} + * to Glide instead. It's almost always better to allow Glide to load {@link Bitmap}s than + * pass {@link Bitmap}s into Glide. If you have a custom way to obtain {@link Bitmap}s that is + * not supported by Glide, consider registering a custom + * {@link com.bumptech.glide.load.model.ModelLoader} or + * {@link com.bumptech.glide.load.ResourceDecoder} instead. + * + *

The {@link DiskCacheStrategy} is set to {@link DiskCacheStrategy#NONE}. Using other + * strategies may result in undefined behavior. + * + *

In memory caching relies on Object equality. The contents of the {@link Bitmap}s are not + * compared. + * + * @see #load(Object) + */ + @CheckResult + public RequestBuilder load(@Nullable Bitmap bitmap) { + return loadGeneric(bitmap) + .apply(diskCacheStrategyOf(DiskCacheStrategy.NONE)); + } + + /** + * Returns a request builder to load the given {@link Drawable}. + * + *

{@link Drawable}s provided to this method become owned by Glide. They or {@link Bitmap}s + * they contain may be recycled or re-used at any time. If you do not own the {@link Drawable}, + * do not pass it in to Glide. It's almost always better to allow Glide to load {@link Bitmap}s + * than pass {@link Bitmap}s into Glide. If you have a custom way to obtain {@link Bitmap}s that + * is not supported by Glide, consider registering a custom + * {@link com.bumptech.glide.load.model.ModelLoader} or + * {@link com.bumptech.glide.load.ResourceDecoder} instead. + * + *

The {@link DiskCacheStrategy} is set to {@link DiskCacheStrategy#NONE}. Using other + * strategies may result in undefined behavior. + * + *

In memory caching relies on Object equality. The contents of the {@link Drawable}s are not + * compared. + * + * @see #load(Object) + */ + @CheckResult + public RequestBuilder load(@Nullable Drawable drawable) { + return loadGeneric(drawable) + .apply(diskCacheStrategyOf(DiskCacheStrategy.NONE)); + } + + /** + * Returns a request builder to load the given {@link java.lang.String}. * *

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 diff --git a/library/src/main/java/com/bumptech/glide/load/resource/bitmap/UnitBitmapDecoder.java b/library/src/main/java/com/bumptech/glide/load/resource/bitmap/UnitBitmapDecoder.java new file mode 100644 index 000000000..1320a2d8b --- /dev/null +++ b/library/src/main/java/com/bumptech/glide/load/resource/bitmap/UnitBitmapDecoder.java @@ -0,0 +1,30 @@ +package com.bumptech.glide.load.resource.bitmap; + +import android.graphics.Bitmap; +import android.support.annotation.Nullable; +import com.bumptech.glide.load.Options; +import com.bumptech.glide.load.ResourceDecoder; +import com.bumptech.glide.load.engine.Resource; +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import java.io.IOException; + +public final class UnitBitmapDecoder implements ResourceDecoder { + + private final BitmapPool bitmapPool; + + public UnitBitmapDecoder(BitmapPool bitmapPool) { + this.bitmapPool = bitmapPool; + } + + @Override + public boolean handles(Bitmap source, Options options) throws IOException { + return true; + } + + @Nullable + @Override + public Resource decode(Bitmap source, int width, int height, Options options) + throws IOException { + return new BitmapResource(source, bitmapPool); + } +} diff --git a/library/src/main/java/com/bumptech/glide/load/resource/drawable/DrawableResourceImpl.java b/library/src/main/java/com/bumptech/glide/load/resource/drawable/DrawableResourceImpl.java new file mode 100644 index 000000000..3808b60d4 --- /dev/null +++ b/library/src/main/java/com/bumptech/glide/load/resource/drawable/DrawableResourceImpl.java @@ -0,0 +1,45 @@ +package com.bumptech.glide.load.resource.drawable; + +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import com.bumptech.glide.load.engine.Resource; +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import com.bumptech.glide.load.resource.bitmap.BitmapDrawableResource; + +/** + * Handles generic {@link Drawable} types where we may be uncertain of their size or type. + */ +final class DrawableResourceImpl extends DrawableResource { + + @SuppressWarnings("unchecked") + public static Resource newInstance(Drawable drawable, BitmapPool bitmapPool) { + if (drawable instanceof BitmapDrawable) { + BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; + return (Resource) (Resource) + new BitmapDrawableResource(bitmapDrawable, bitmapPool); + } + return new DrawableResourceImpl(drawable); + } + + private DrawableResourceImpl(Drawable drawable) { + super(drawable); + } + + @SuppressWarnings("unchecked") + @Override + public Class getResourceClass() { + return (Class) drawable.getClass(); + } + + @Override + public int getSize() { + // 4 bytes per pixel for ARGB_8888 Bitmaps is something of a reasonable approximation. If + // there are no intrinsic bounds, we can fall back just to 1. + return Math.max(1, drawable.getIntrinsicWidth() * drawable.getIntrinsicHeight() * 4); + } + + @Override + public void recycle() { + // Do nothing. + } +} diff --git a/library/src/main/java/com/bumptech/glide/load/resource/drawable/ResourceDrawableDecoder.java b/library/src/main/java/com/bumptech/glide/load/resource/drawable/ResourceDrawableDecoder.java index 376ebbc26..2bdc8f35e 100644 --- a/library/src/main/java/com/bumptech/glide/load/resource/drawable/ResourceDrawableDecoder.java +++ b/library/src/main/java/com/bumptech/glide/load/resource/drawable/ResourceDrawableDecoder.java @@ -3,7 +3,6 @@ package com.bumptech.glide.load.resource.drawable; import android.content.ContentResolver; import android.content.Context; import android.content.pm.PackageManager.NameNotFoundException; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.support.annotation.DrawableRes; @@ -12,7 +11,6 @@ import com.bumptech.glide.load.Options; import com.bumptech.glide.load.ResourceDecoder; import com.bumptech.glide.load.engine.Resource; import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; -import com.bumptech.glide.load.resource.bitmap.BitmapDrawableResource; import java.io.IOException; import java.util.List; @@ -56,17 +54,7 @@ public class ResourceDrawableDecoder implements ResourceDecoder { ? context : getContextForPackage(source, packageName); // We can't get a theme from another application. Drawable drawable = DrawableDecoderCompat.getDrawable(toUse, resId); - return getDrawableResource(drawable); - } - - @SuppressWarnings("unchecked") - private Resource getDrawableResource(Drawable drawable) { - if (drawable instanceof BitmapDrawable) { - BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; - return (Resource) (Resource) - new BitmapDrawableResource(bitmapDrawable, bitmapPool); - } - return new InternalDrawableResource(drawable); + return DrawableResourceImpl.newInstance(drawable, bitmapPool); } @NonNull @@ -103,29 +91,4 @@ public class ResourceDrawableDecoder implements ResourceDecoder { } return result; } - - private static final class InternalDrawableResource extends DrawableResource { - - InternalDrawableResource(Drawable drawable) { - super(drawable); - } - - @SuppressWarnings("unchecked") - @Override - public Class getResourceClass() { - return (Class) drawable.getClass(); - } - - @Override - public int getSize() { - // 4 bytes per pixel for ARGB_8888 Bitmaps is something of a reasonable approximation. If - // there are no intrinsic bounds, we can fall back just to 1. - return Math.max(1, drawable.getIntrinsicWidth() * drawable.getIntrinsicHeight() * 4); - } - - @Override - public void recycle() { - // Do nothing. - } - } } diff --git a/library/src/main/java/com/bumptech/glide/load/resource/drawable/UnitDrawableDecoder.java b/library/src/main/java/com/bumptech/glide/load/resource/drawable/UnitDrawableDecoder.java new file mode 100644 index 000000000..6690a0108 --- /dev/null +++ b/library/src/main/java/com/bumptech/glide/load/resource/drawable/UnitDrawableDecoder.java @@ -0,0 +1,32 @@ +package com.bumptech.glide.load.resource.drawable; + +import android.graphics.drawable.Drawable; +import android.support.annotation.Nullable; +import com.bumptech.glide.load.Options; +import com.bumptech.glide.load.ResourceDecoder; +import com.bumptech.glide.load.engine.Resource; +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import java.io.IOException; + +/** + * Passes through a {@link Drawable} as a {@link Drawable} based {@link Resource}. + */ +public class UnitDrawableDecoder implements ResourceDecoder { + private final BitmapPool bitmapPool; + + public UnitDrawableDecoder(BitmapPool bitmapPool) { + this.bitmapPool = bitmapPool; + } + + @Override + public boolean handles(Drawable source, Options options) throws IOException { + return true; + } + + @Nullable + @Override + public Resource decode(Drawable source, int width, int height, Options options) + throws IOException { + return DrawableResourceImpl.newInstance(source, bitmapPool); + } +} diff --git a/library/src/test/java/com/bumptech/glide/GlideTest.java b/library/src/test/java/com/bumptech/glide/GlideTest.java index dfb45ba0c..1406a02f7 100644 --- a/library/src/test/java/com/bumptech/glide/GlideTest.java +++ b/library/src/test/java/com/bumptech/glide/GlideTest.java @@ -3,8 +3,10 @@ package com.bumptech.glide; import static com.bumptech.glide.request.RequestOptions.decodeTypeOf; import static com.bumptech.glide.request.RequestOptions.errorOf; import static com.bumptech.glide.request.RequestOptions.placeholderOf; +import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isA; @@ -70,6 +72,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.robolectric.RobolectricTestRunner; @@ -554,6 +557,40 @@ public class GlideTest { verify(target).onLoadFailed(eq(error)); } + @Test + public void testLoadBitmap_asBitmap() { + Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); + requestManager + .asBitmap() + .load(bitmap) + .into(target); + + verify(target).onResourceReady(eq(bitmap), any(Transition.class)); + } + + @Test + public void testLoadBitmap_asDrawable() { + Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); + requestManager + .load(bitmap) + .into(target); + + ArgumentCaptor captor = ArgumentCaptor.forClass(Object.class); + verify(target).onResourceReady(captor.capture(), any(Transition.class)); + BitmapDrawable drawable = (BitmapDrawable) captor.getValue(); + assertThat(drawable.getBitmap()).isEqualTo(bitmap); + } + + @Test + public void testLoadDrawable() { + Drawable drawable = new ColorDrawable(Color.RED); + requestManager + .load(drawable) + .into(target); + + verify(target).onResourceReady(eq(drawable), any(Transition.class)); + } + @Test public void testNullModelPrefersFallbackDrawable() { Drawable placeholder = new ColorDrawable(Color.GREEN); -- GitLab