@Override public void onResourceRemoved(@NonNull Resource<?> removed) { if (removed == first) { cache.put(firstKey, first); } } });
@Override public synchronized void onResourceReleased(Key cacheKey, EngineResource<?> resource) { activeResources.deactivate(cacheKey); if (resource.isCacheable()) { cache.put(cacheKey, resource); } else { resourceRecycler.recycle(resource); } }
@Before public void setUp() { MockitoAnnotations.initMocks(this); doAnswer(new AddBitmapPoolAnswer(addedBitmaps)).when(pool).put(any(Bitmap.class)); when(pool.getDirty(anyInt(), anyInt(), any(Bitmap.Config.class))) .thenAnswer(new CreateBitmap()); when(cache.put(any(Key.class), anyResource())) .thenAnswer(new AddBitmapCacheAnswer(addedBitmaps)); }
@Test public void testResourceIsNotAddedToCacheOnReleasedIfNotCacheable() { when(harness.resource.isCacheable()).thenReturn(false); harness.getEngine().onResourceReleased(harness.cacheKey, harness.resource); verify(harness.cache, never()).put(eq(harness.cacheKey), eq(harness.resource)); }
@Test public void testAddsBitmapsToMemoryCacheIfMemoryCacheHasEnoughSpaceRemaining() { Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); when(cache.getMaxSize()).thenReturn(Long.valueOf(Util.getBitmapByteSize(bitmap))); PreFillType size = new PreFillType.Builder(bitmap.getWidth(), bitmap.getHeight()).setConfig(bitmap.getConfig()) .build(); Map<PreFillType, Integer> allocationOrder = new HashMap<>(); allocationOrder.put(size, 1); getHandler(allocationOrder).run(); verify(cache).put(any(Key.class), anyResource()); verify(pool, never()).put(any(Bitmap.class)); // TODO(b/20335397): This code was relying on Bitmap equality which Robolectric removed // assertThat(addedBitmaps).containsExactly(bitmap); }
@Test public void testResourceIsAddedToCacheOnReleased() { final Object expected = new Object(); when(harness.resource.isCacheable()).thenReturn(true); when(harness.resource.get()).thenReturn(expected); doAnswer( new Answer<Void>() { @Override public Void answer(InvocationOnMock invocationOnMock) { Resource<?> resource = (Resource<?>) invocationOnMock.getArguments()[1]; assertEquals(expected, resource.get()); return null; } }) .when(harness.cache) .put(eq(harness.cacheKey), anyResource()); harness.getEngine().onResourceReleased(harness.cacheKey, harness.resource); verify(harness.cache).put(eq(harness.cacheKey), anyResource()); }
@Test public void testAddsBitmapsToBitmapPoolIfMemoryCacheIsFull() { Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); when(cache.getMaxSize()).thenReturn(0L); PreFillType size = new PreFillType.Builder(bitmap.getWidth(), bitmap.getHeight()).setConfig(bitmap.getConfig()) .build(); Map<PreFillType, Integer> allocationOrder = new HashMap<>(); allocationOrder.put(size, 1); getHandler(allocationOrder).run(); verify(cache, never()).put(any(Key.class), anyResource()); // TODO(b/20335397): This code was relying on Bitmap equality which Robolectric removed // verify(pool).put(eq(bitmap)); // assertThat(addedBitmaps).containsExactly(bitmap); }
@Test public void testAddsBitmapsToPoolIfMemoryCacheIsNotFullButCannotFitBitmap() { Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); when(cache.getMaxSize()).thenReturn((long) Util.getBitmapByteSize(bitmap) / 2); PreFillType size = new PreFillType.Builder(bitmap.getWidth(), bitmap.getHeight()).setConfig(bitmap.getConfig()) .build(); Map<PreFillType, Integer> allocationOrder = new HashMap<>(); allocationOrder.put(size, 1); getHandler(allocationOrder).run(); verify(cache, never()).put(any(Key.class), anyResource()); // TODO(b/20335397): This code was relying on Bitmap equality which Robolectric removed //verify(pool).put(eq(bitmap)); //assertThat(addedBitmaps).containsExactly(bitmap); }
memoryCache.put(uniqueKey, BitmapResource.obtain(bitmap, bitmapPool)); } else { bitmapPool.put(bitmap);
@Test public void testPreventEviction() { final MemoryCache cache = new LruResourceCache(100); final Resource<?> first = getResource(30); final Key firstKey = new MockKey(); cache.put(firstKey, first); Resource<?> second = getResource(30); Key secondKey = new MockKey(); cache.put(secondKey, second); Resource<?> third = getResource(30); Key thirdKey = new MockKey(); cache.put(thirdKey, third); cache.setResourceRemovedListener(new ResourceRemovedListener() { @Override public void onResourceRemoved(@NonNull Resource<?> removed) { if (removed == first) { cache.put(firstKey, first); } } }); // trims from 100 to 50, having 30+30+30 items, it should trim to 1 item cache.trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); // and that 1 item must be first, because it's forced to return to cache in the listener @SuppressWarnings("unchecked") LruCache<Key, Resource<?>> lruCache = (LruCache<Key, Resource<?>>) cache; assertTrue(lruCache.contains(firstKey)); assertFalse(lruCache.contains(secondKey)); assertFalse(lruCache.contains(thirdKey)); }
@Override public void onResourceReleased(Key cacheKey, EngineResource resource) { Util.assertMainThread(); activeResources.remove(cacheKey); if (resource.isCacheable()) { cache.put(cacheKey, resource); } else { resourceRecycler.recycle(resource); } }
/** * Attempts to allocate {@link Bitmap}s and returns {@code true} if there are more * {@link Bitmap}s to allocate and {@code false} otherwise. */ private boolean allocate() { long start = clock.now(); while (!toPrefill.isEmpty() && !isGcDetected(start)) { PreFillType toAllocate = toPrefill.remove(); Bitmap bitmap = Bitmap.createBitmap(toAllocate.getWidth(), toAllocate.getHeight(), toAllocate.getConfig()); // Don't over fill the memory cache to avoid evicting useful resources, but make sure it's not empty so // we use all available space. if (getFreeMemoryCacheBytes() >= Util.getBitmapByteSize(bitmap)) { memoryCache.put(new UniqueKey(), BitmapResource.obtain(bitmap, bitmapPool)); } else { addToBitmapPool(toAllocate, bitmap); } if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "allocated [" + toAllocate.getWidth() + "x" + toAllocate.getHeight() + "] " + toAllocate.getConfig() + " size: " + Util.getBitmapByteSize(bitmap)); } } return !isCancelled && !toPrefill.isEmpty(); }
@Override public void onResourceReleased(Key cacheKey, EngineResource resource) { Util.assertMainThread(); activeResources.remove(cacheKey); if (resource.isCacheable()) { cache.put(cacheKey, resource); } else { resourceRecycler.recycle(resource); } }
memoryCache.put(new UniqueKey(), BitmapResource.obtain(bitmap, bitmapPool)); } else { bitmapPool.put(bitmap);