diff --git a/library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifDrawableTest.java b/library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifDrawableTest.java index abfc060630708736561158ab9d79a270d0c812a0..c737892748cd3d644206d3d1add4f874e3096d38 100644 --- a/library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifDrawableTest.java +++ b/library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifDrawableTest.java @@ -67,7 +67,8 @@ public class GifDrawableTest { public void testShouldNotDrawNullBitmapFrame() { Canvas canvas = mock(Canvas.class); drawable = new GifDrawable(gifDecoder, frameManager, firstFrame, bitmapPool); - drawable.onFrameRead(null, 0); + drawable.onFrameRead(0); + when(frameManager.getCurrentFrame()).thenReturn(null); drawable.draw(canvas); verify(canvas).drawBitmap(eq(firstFrame), anyInt(), anyInt(), any(Paint.class)); @@ -82,6 +83,17 @@ public class GifDrawableTest { verify(canvas, never()).drawBitmap(any(Bitmap.class), anyInt(), anyInt(), any(Paint.class)); } + @Test + public void testDoesDrawCurrentFrameIfOneIsAvailable() { + Canvas canvas = mock(Canvas.class); + Bitmap currentFrame = Bitmap.createBitmap(100123, 123141, Bitmap.Config.ARGB_4444); + when(frameManager.getCurrentFrame()).thenReturn(currentFrame); + + drawable.draw(canvas); + verify(canvas).drawBitmap(eq(currentFrame), anyInt(), anyInt(), any(Paint.class)); + verify(canvas, never()).drawBitmap(eq(firstFrame), anyInt(), anyInt(), any(Paint.class)); + } + @Test public void testRequestsNextFrameOnStart() { drawable.setVisible(true, true); @@ -156,7 +168,7 @@ public class GifDrawableTest { @Test public void testStartsLoadingNextFrameWhenCurrentFinishes() { drawable.setIsRunning(true); - drawable.onFrameRead(Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888), 0); + drawable.onFrameRead(0); verify(frameManager).getNextFrame(eq(drawable)); } @@ -164,7 +176,7 @@ public class GifDrawableTest { @Test public void testInvalidatesSelfWhenFrameReady() { drawable.setIsRunning(true); - drawable.onFrameRead(Bitmap.createBitmap(100, 100, Bitmap.Config.RGB_565), 0); + drawable.onFrameRead(0); verify(cb).invalidateDrawable(eq(drawable)); } @@ -172,7 +184,7 @@ public class GifDrawableTest { @Test public void testDoesNotStartLoadingNextFrameWhenCurrentFinishesIfNotRunning() { drawable.setIsRunning(false); - drawable.onFrameRead(Bitmap.createBitmap(10, 100, Bitmap.Config.ARGB_8888), 0); + drawable.onFrameRead(0); verify(frameManager, never()).getNextFrame(eq(drawable)); } @@ -181,7 +193,7 @@ public class GifDrawableTest { public void testDoesNotStartLoadingNextFrameWhenCurrentFinishesIfHasNoCallback() { drawable.setIsRunning(true); drawable.setCallback(null); - drawable.onFrameRead(Bitmap.createBitmap(1, 2, Bitmap.Config.ARGB_8888), 0); + drawable.onFrameRead(0); verify(frameManager, never()).getNextFrame(eq(drawable)); } @@ -190,7 +202,7 @@ public class GifDrawableTest { public void testStopsWhenCurrentFrameFinishesIfHasNoCallback() { drawable.setIsRunning(true); drawable.setCallback(null); - drawable.onFrameRead(Bitmap.createBitmap(2, 1, Bitmap.Config.ARGB_8888), 0); + drawable.onFrameRead(0); assertFalse(drawable.isRunning()); } @@ -382,13 +394,13 @@ public class GifDrawableTest { drawable.setVisible(true, true); drawable.start(); - drawable.onFrameRead(getBitmap(), 0); - drawable.onFrameRead(getBitmap(), 1); + drawable.onFrameRead(0); + drawable.onFrameRead(1); drawable.start(); - drawable.onFrameRead(getBitmap(), 0); - drawable.onFrameRead(getBitmap(), 1); + drawable.onFrameRead(0); + drawable.onFrameRead(1); verify(frameManager, times(4)).getNextFrame(eq(drawable)); assertFalse(drawable.isRunning()); @@ -437,10 +449,23 @@ public class GifDrawableTest { verify(frameManager, times(frameCount * loopCount)).getNextFrame(eq(drawable)); } + @Test + public void testDoesNotDrawFrameAfterRecycle() { + Bitmap bitmap = Bitmap.createBitmap(100, 112341, Bitmap.Config.RGB_565); + drawable.setVisible(true, true); + drawable.start(); + when(frameManager.getCurrentFrame()).thenReturn(bitmap); + drawable.onFrameRead(1); + drawable.recycle(); + Canvas canvas = mock(Canvas.class); + drawable.draw(canvas); + verify(canvas, never()).drawBitmap(any(Bitmap.class), anyInt(), anyInt(), any(Paint.class)); + } + private void runLoops(int loopCount, int frameCount) { for (int loop = 0; loop < loopCount; loop++) { for (int frame = 0; frame < frameCount; frame++) { - drawable.onFrameRead(getBitmap(), frame); + drawable.onFrameRead(frame); } } } diff --git a/library/src/main/java/com/bumptech/glide/load/resource/gif/GifDrawable.java b/library/src/main/java/com/bumptech/glide/load/resource/gif/GifDrawable.java index 85c539ac10261642db37c97ebb0c62c28120a7ac..0f2e649e0928739186a2b1c4c6f1b4fd12849d41 100644 --- a/library/src/main/java/com/bumptech/glide/load/resource/gif/GifDrawable.java +++ b/library/src/main/java/com/bumptech/glide/load/resource/gif/GifDrawable.java @@ -26,8 +26,6 @@ public class GifDrawable extends GlideDrawable implements GifFrameManager.FrameC private final GifState state; private final GifDecoder decoder; - /** The current frame to draw, or null if no frame has been loaded yet. */ - private Bitmap currentFrame; /** True if the drawable is currently animating. */ private boolean isRunning; /** True if the drawable should animate while visible. */ @@ -181,6 +179,10 @@ public class GifDrawable extends GlideDrawable implements GifFrameManager.FrameC @Override public void draw(Canvas canvas) { + if (isRecycled) { + return; + } + Bitmap currentFrame = frameManager.getCurrentFrame(); Bitmap toDraw = currentFrame != null ? currentFrame : state.firstFrame; canvas.drawBitmap(toDraw, 0, 0, paint); } @@ -203,7 +205,7 @@ public class GifDrawable extends GlideDrawable implements GifFrameManager.FrameC @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override - public void onFrameRead(Bitmap frame, int frameIndex) { + public void onFrameRead(int frameIndex) { if (Build.VERSION_CODES.HONEYCOMB <= Build.VERSION.SDK_INT && getCallback() == null) { stop(); return; @@ -212,10 +214,7 @@ public class GifDrawable extends GlideDrawable implements GifFrameManager.FrameC return; } - if (frame != null) { - currentFrame = frame; - invalidateSelf(); - } + invalidateSelf(); if (frameIndex == decoder.getFrameCount() - 1) { loopCount++; diff --git a/library/src/main/java/com/bumptech/glide/load/resource/gif/GifFrameManager.java b/library/src/main/java/com/bumptech/glide/load/resource/gif/GifFrameManager.java index 32dce79a36af50342b3b08de9fa86598b3b787b0..3c56fdf4df0585a53fb426de8501514e3ab86630 100644 --- a/library/src/main/java/com/bumptech/glide/load/resource/gif/GifFrameManager.java +++ b/library/src/main/java/com/bumptech/glide/load/resource/gif/GifFrameManager.java @@ -2,6 +2,7 @@ package com.bumptech.glide.load.resource.gif; import android.content.Context; import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Looper; import android.os.SystemClock; @@ -35,7 +36,7 @@ class GifFrameManager { private DelayTarget next; public interface FrameCallback { - void onFrameRead(Bitmap frame, int index); + void onFrameRead(int index); } public GifFrameManager(Context context, GifDecoder decoder, Transformation transformation, int targetWidth, @@ -92,6 +93,10 @@ class GifFrameManager { .into(next); } + public Bitmap getCurrentFrame() { + return current != null ? current.resource : null; + } + public void clear() { if (current != null) { mainHandler.removeCallbacks(current); @@ -127,11 +132,16 @@ class GifFrameManager { @Override public void run() { - cb.onFrameRead(resource, index); + cb.onFrameRead(index); if (current != null) { Glide.clear(current); } current = this; } + + @Override + public void onLoadCleared(Drawable placeholder) { + resource = null; + } } }