From 05910d7bb9e9aafdf85893227d1dd50b82266771 Mon Sep 17 00:00:00 2001 From: Sam Judd Date: Tue, 28 Oct 2014 11:02:44 -0700 Subject: [PATCH] Do a get before put when pre filling. Otherwise it's likely our new Bitmaps will be immediately evicted. --- .../engine/prefill/PreFillerHandlerTest.java | 58 +++++++++++++++---- .../prefill/BitmapPreFillIdleHandler.java | 11 ++++ 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/library/src/androidTest/java/com/bumptech/glide/load/engine/prefill/PreFillerHandlerTest.java b/library/src/androidTest/java/com/bumptech/glide/load/engine/prefill/PreFillerHandlerTest.java index 64f17d4f1..49c7b6041 100644 --- a/library/src/androidTest/java/com/bumptech/glide/load/engine/prefill/PreFillerHandlerTest.java +++ b/library/src/androidTest/java/com/bumptech/glide/load/engine/prefill/PreFillerHandlerTest.java @@ -10,6 +10,7 @@ import com.bumptech.glide.util.Util; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.InOrder; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.robolectric.RobolectricTestRunner; @@ -27,8 +28,10 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -50,10 +53,6 @@ public class PreFillerHandlerTest { } private BitmapPreFillIdleHandler getHandler(Map allocationOrder) { - int total = 0; - for (Integer count : allocationOrder.values()) { - total += count; - } return new BitmapPreFillIdleHandler(pool, cache, new PreFillQueue(allocationOrder), clock); } @@ -159,8 +158,7 @@ public class PreFillerHandlerTest { Map allocationOrder = new HashMap(); allocationOrder.put(size, 1); - BitmapPreFillIdleHandler handler = getHandler(allocationOrder); - handler.queueIdle(); + getHandler(allocationOrder).queueIdle(); verify(cache).put(any(Key.class), any(Resource.class)); verify(pool, never()).put(any(Bitmap.class)); @@ -177,8 +175,7 @@ public class PreFillerHandlerTest { Map allocationOrder = new HashMap(); allocationOrder.put(size, 1); - BitmapPreFillIdleHandler handler = getHandler(allocationOrder); - handler.queueIdle(); + getHandler(allocationOrder).queueIdle(); verify(cache, never()).put(any(Key.class), any(Resource.class)); verify(pool).put(eq(bitmap)); @@ -195,14 +192,55 @@ public class PreFillerHandlerTest { Map allocationOrder = new HashMap(); allocationOrder.put(size, 1); - BitmapPreFillIdleHandler handler = getHandler(allocationOrder); - handler.queueIdle(); + getHandler(allocationOrder).queueIdle(); verify(cache, never()).put(any(Key.class), any(Resource.class)); verify(pool).put(eq(bitmap)); assertThat(addedBitmaps, contains(bitmap)); } + @Test + public void testDoesAGetFromPoolBeforeAddingForEachSize() { + Bitmap first = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_4444); + PreFillBitmapAttribute firstSize = new PreFillBitmapAttribute(first.getWidth(), first.getHeight(), + first.getConfig(), 1); + + Bitmap second = Bitmap.createBitmap(200, 200, Bitmap.Config.RGB_565); + PreFillBitmapAttribute secondSize = new PreFillBitmapAttribute(second.getWidth(), second.getHeight(), + second.getConfig(), 1); + + Map allocationOrder = new HashMap(); + allocationOrder.put(firstSize, 1); + allocationOrder.put(secondSize, 1); + + getHandler(allocationOrder).queueIdle(); + + InOrder firstOrder = inOrder(pool); + firstOrder.verify(pool).get(eq(first.getWidth()), eq(first.getHeight()), eq(first.getConfig())); + firstOrder.verify(pool).put(eq(first)); + + InOrder secondOrder = inOrder(pool); + secondOrder.verify(pool).get(eq(second.getWidth()), eq(second.getHeight()), eq(second.getConfig())); + secondOrder.verify(pool).put(eq(second)); + } + + @Test + public void testDoesNotGetMoreThanOncePerSize() { + Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_4444); + PreFillBitmapAttribute size = new PreFillBitmapAttribute(bitmap.getWidth(), bitmap.getHeight(), + bitmap.getConfig(), 1); + + final int numBitmaps = 5; + Map allocationOrder = new HashMap(); + allocationOrder.put(size, numBitmaps); + + getHandler(allocationOrder).queueIdle(); + + InOrder order = inOrder(pool); + order.verify(pool).get(eq(bitmap.getWidth()), eq(bitmap.getHeight()), eq(bitmap.getConfig())); + order.verify(pool, times(numBitmaps)).put(eq(bitmap)); + } + private static class AddBitmapPoolAnswer implements Answer { private List bitmaps; diff --git a/library/src/main/java/com/bumptech/glide/load/engine/prefill/BitmapPreFillIdleHandler.java b/library/src/main/java/com/bumptech/glide/load/engine/prefill/BitmapPreFillIdleHandler.java index d1668d279..1d32f4ed4 100644 --- a/library/src/main/java/com/bumptech/glide/load/engine/prefill/BitmapPreFillIdleHandler.java +++ b/library/src/main/java/com/bumptech/glide/load/engine/prefill/BitmapPreFillIdleHandler.java @@ -12,6 +12,8 @@ import com.bumptech.glide.util.Util; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; +import java.util.HashSet; +import java.util.Set; /** * A class that allocates {@link android.graphics.Bitmap Bitmaps} when the main thread runs out of messages so that the @@ -28,6 +30,8 @@ final class BitmapPreFillIdleHandler implements MessageQueue.IdleHandler { private final MemoryCache memoryCache; private final PreFillQueue toPrefill; private final Clock clock; + private final Set seenAttributes = + new HashSet(); private boolean isCancelled; @@ -62,6 +66,13 @@ final class BitmapPreFillIdleHandler implements MessageQueue.IdleHandler { if ((memoryCache.getMaxSize() - memoryCache.getCurrentSize()) >= Util.getBitmapByteSize(bitmap)) { memoryCache.put(new UniqueKey(), BitmapResource.obtain(bitmap, bitmapPool)); } else { + if (seenAttributes.add(toAllocate)) { + Bitmap fromPool = bitmapPool.get(toAllocate.getWidth(), toAllocate.getHeight(), + toAllocate.getConfig()); + if (fromPool != null) { + bitmapPool.put(fromPool); + } + } bitmapPool.put(bitmap); } -- GitLab