提交 15799329 编写于 作者: S Sam Judd

Avoid drawing recycled Bitmaps in GifDrawable.

Fixes #202.
上级 85577627
......@@ -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);
}
}
}
......
......@@ -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++;
......
......@@ -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<Bitmap> 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;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册