private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) { if (resource instanceof Initializable) { ((Initializable) resource).initialize(); } Resource<R> result = resource; LockedResource<R> lockedResource = null; if (deferredEncodeManager.hasResourceToEncode()) { lockedResource = LockedResource.obtain(resource); result = lockedResource; } notifyComplete(result, dataSource); stage = Stage.ENCODE; try { if (deferredEncodeManager.hasResourceToEncode()) { deferredEncodeManager.encode(diskCacheProvider, options); } } finally { if (lockedResource != null) { lockedResource.unlock(); } onEncodeComplete(); } }
private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data, DataSource dataSource) throws GlideException { try { if (data == null) { return null; } long startTime = LogTime.getLogTime(); Resource<R> result = decodeFromFetcher(data, dataSource); if (Log.isLoggable(TAG, Log.VERBOSE)) { logWithTimeAndKey("Decoded result " + result, startTime); } return result; } finally { fetcher.cleanup(); } }
@Override public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) { this.currentSourceKey = sourceKey; this.currentData = data; this.currentFetcher = fetcher; this.currentDataSource = dataSource; this.currentAttemptingKey = attemptedKey; if (Thread.currentThread() != currentThread) { runReason = RunReason.DECODE_DATA; callback.reschedule(this); } else { TraceCompat.beginSection("DecodeJob.decodeFromRetrievedData"); try { decodeFromRetrievedData(); } finally { TraceCompat.endSection(); } } }
@Test public void testFactoryReturnsNoAnimationIfFromMemoryCache() { Transition<Object> animation = factory.build(DataSource.MEMORY_CACHE, true /*isFirstResource*/); assertEquals(NoTransition.get(), animation); verify(viewTransitionAnimationFactory, never()).build(RuntimeEnvironment.application); }
@Test public void load_afterResourceIsLoadedInActiveResources_returnsFromMemoryCache() { when(harness.resource.isCacheable()).thenReturn(true); doAnswer(new Answer<Object>() { @Override public Object answer(InvocationOnMock invocationOnMock) throws Throwable { harness.getEngine().onEngineJobComplete(harness.cacheKey, harness.resource); return null; } }).when(harness.job).start(any(DecodeJob.class)); harness.doLoad(); harness.doLoad(); verify(harness.cb).onResourceReady(any(Resource.class), eq(DataSource.MEMORY_CACHE)); }
@Override public Transition<Drawable> build(DataSource dataSource, boolean isFirstResource) { if (dataSource == DataSource.MEMORY_CACHE) { return NoTransition.get(); } else if (isFirstResource) { return getFirstResourceTransition(dataSource); } else { return getSecondResourceTransition(dataSource); } }
@Test public void testRequestListenerIsCalledWithLoadedFromMemoryIfLoadCompletesSynchronously() { final SingleRequest<List> request = builder.build(); when(builder.engine .load( eq(builder.glideContext), eq(builder.model), eq(builder.signature), anyInt(), anyInt(), eq(Object.class), eq(List.class), any(Priority.class), any(DiskCacheStrategy.class), eq(builder.transformations), anyBoolean(), anyBoolean(), any(Options.class), anyBoolean(), anyBoolean(), /*useAnimationPool=*/ anyBoolean(), anyBoolean(), any(ResourceCallback.class))) .thenAnswer(new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { request.onResourceReady(builder.resource, DataSource.MEMORY_CACHE); return null; } }); request.begin(); request.onSizeReady(100, 100); verify(builder.requestListener) .onResourceReady(eq(builder.result), any(Number.class), isAListTarget(), eq(DataSource.MEMORY_CACHE), anyBoolean()); }
@Test public void testCanHandleEmptyResources() { SingleRequest<List> request = builder.build(); when(builder.resource.get()).thenReturn(null); request.onResourceReady(builder.resource, DataSource.REMOTE); assertTrue(request.isFailed()); verify(builder.engine).release(eq(builder.resource)); verify(builder.requestListener).onLoadFailed(isAGlideException(), any(Number.class), eq(builder.target), anyBoolean()); }
@Test public void testRequestListenerIsCalledWithNotIsFirstRequestIfRequestCoordinatorReturnsResourceSet() { SingleRequest<List> request = builder.build(); when(builder.requestCoordinator.isAnyResourceSet()).thenReturn(true); request.onResourceReady(builder.resource, DataSource.DATA_DISK_CACHE); verify(builder.requestListener) .onResourceReady(eq(builder.result), any(Number.class), isAListTarget(), isADataSource(), eq(false)); }
@Test public void testRequestListenerIsCalledWithTarget() { SingleRequest<List> request = builder.build(); request.onResourceReady(builder.resource, DataSource.DATA_DISK_CACHE); verify(builder.requestListener) .onResourceReady(any(List.class), any(Number.class), eq(builder.target), isADataSource(), anyBoolean()); }
@Test public void testRequestListenerIsCalledWithResourceResult() { SingleRequest<List> request = builder.build(); request.onResourceReady(builder.resource, DataSource.DATA_DISK_CACHE); verify(builder.requestListener) .onResourceReady(eq(builder.result), any(Number.class), isAListTarget(), isADataSource(), anyBoolean()); }
@Test public void testCanHandleNullResources() { SingleRequest<List> request = builder.build(); request.onResourceReady(null, DataSource.LOCAL); assertTrue(request.isFailed()); verify(builder.requestListener).onLoadFailed(isAGlideException(), isA(Number.class), eq(builder.target), anyBoolean()); }
@Test public void testReturnsResourceOnGetIfAlreadyDone() throws ExecutionException, InterruptedException { Object expected = new Object(); future.onResourceReady( /*resource=*/ expected, /*model=*/ null, /*target=*/future, DataSource.DATA_DISK_CACHE, true /*isFirstResource*/); assertEquals(expected, future.get()); }
@Test public void testResourceIsReturnedFromActiveResourcesIfPresent() { harness.activeResources.activate(harness.cacheKey, harness.resource); harness.doLoad(); verify(harness.cb).onResourceReady(eq(harness.resource), eq(DataSource.MEMORY_CACHE)); }
@Test public void testRequestListenerIsCalledWithModel() { SingleRequest<List> request = builder.build(); request.onResourceReady(builder.resource, DataSource.DATA_DISK_CACHE); verify(builder.requestListener) .onResourceReady(any(List.class), eq(builder.model), isAListTarget(), isADataSource(), anyBoolean()); }
@Override public void onDataFetcherFailed(Key attemptedKey, Exception e, DataFetcher<?> fetcher, DataSource dataSource) { fetcher.cleanup(); GlideException exception = new GlideException("Fetching data failed", e); exception.setLoggingDetails(attemptedKey, dataSource, fetcher.getDataClass()); exceptions.add(exception); if (Thread.currentThread() != currentThread) { runReason = RunReason.SWITCH_TO_SOURCE_SERVICE; callback.reschedule(this); } else { runGenerators(); } }
private <Data, ResourceType> Resource<R> runLoadPath(Data data, DataSource dataSource, LoadPath<Data, ResourceType, R> path) throws GlideException { DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data); try { return path.load(rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource)); } finally { rewinder.cleanup(); } }
@Override public boolean onResourceReady(T resource, Object model, Target<T> target, DataSource dataSource, boolean isFirstResource) { mainHandler.post(new Runnable() { @Override public void run() { countDownLatch.countDown(); } }); return false; }
@Test public void testFactoryReturnsNoAnimationIfNotFirstResource() { Transition<Object> animation = factory.build(DataSource.DATA_DISK_CACHE, false /*isFirstResource*/); assertEquals(NoTransition.get(), animation); verify(viewTransitionAnimationFactory, never()).build(RuntimeEnvironment.application); }
@Test public void testReturnsFalseFromIsCancelledIfCancelledAfterDone() { future.onResourceReady( /*resource=*/ new Object(), /*model=*/ null, /*target=*/future, DataSource.DATA_DISK_CACHE, true /*isFirstResource*/); future.cancel(true); assertFalse(future.isCancelled()); }
@Override public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) { // This data fetcher will be loading from a File and provide the wrong data source, so override // with the data source of the original fetcher cb.onDataFetcherReady(sourceKey, data, fetcher, loadData.fetcher.getDataSource(), sourceKey); }
@Override public boolean isResourceCacheable(boolean isFromAlternateCacheKey, DataSource dataSource, EncodeStrategy encodeStrategy) { return ((isFromAlternateCacheKey && dataSource == DataSource.DATA_DISK_CACHE) || dataSource == DataSource.LOCAL) && encodeStrategy == EncodeStrategy.TRANSFORMED; }
@Test public void testIsNotFailedAfterClear() { SingleRequest<List> request = builder.build(); request.onResourceReady(null, DataSource.DATA_DISK_CACHE); request.clear(); assertFalse(request.isFailed()); }
@Test public void testCanHandleNullResources() { SingleRequest<List> request = harness.getRequest(); request.onResourceReady(null, DataSource.LOCAL); assertTrue(request.isFailed()); verify(harness.requestListener).onLoadFailed(isAGlideException(), isA(Number.class), eq(harness.target), anyBoolean()); }
@Test public void testIsNotFailedAfterBegin() { SingleRequest<List> request = harness.getRequest(); request.onResourceReady(null, DataSource.DATA_DISK_CACHE); request.begin(); assertFalse(request.isFailed()); }
@Test public void testIsCompleteAfterReceivingResource() { SingleRequest<List> request = harness.getRequest(); request.onResourceReady(harness.resource, DataSource.LOCAL); assertTrue(request.isComplete()); }
@Test public void testGetSucceedsOnMainThreadIfDone() throws ExecutionException, InterruptedException { future = new RequestFutureTarget<>(handler, width, height, true, waiter); future.onResourceReady( /*resource=*/ new Object(), /*model=*/ null, /*target=*/future, DataSource.DATA_DISK_CACHE, true /*isFirstResource*/); future.get(); }
@Override public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) { final View view = mViewReference.get(); if (mPosition == startPosition && view != null) { view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { view.getViewTreeObserver().removeOnPreDrawListener(this); startPostponedEnterTransition(); return true; } }); } return false; }
@Test public void testIsNotRunningAfterComplete() { SingleRequest<List> request = harness.getRequest(); request.begin(); request.onResourceReady(harness.resource, DataSource.REMOTE); assertFalse(request.isRunning()); }
@Test public void testDoesNotCallTargetOnResourceReadyIfRequestListenerReturnsTrue() { SingleRequest<List> request = harness.getRequest(); when(harness.requestListener .onResourceReady(any(List.class), any(Number.class), eq(harness.target), isADataSource(), anyBoolean())).thenReturn(true); request.onResourceReady(harness.resource, DataSource.REMOTE); verify(harness.target, never()).onResourceReady(any(List.class), anyTransition()); }
@Test public void testRequestListenerIsCalledWithResourceResult() { SingleRequest<List> request = harness.getRequest(); request.onResourceReady(harness.resource, DataSource.DATA_DISK_CACHE); verify(harness.requestListener) .onResourceReady(eq(harness.result), any(Number.class), isAListTarget(), isADataSource(), anyBoolean()); }
/** Tests #2555. */ @Test public void onStop_withRequestWithOnlyFullInProgress_nullsOutDrawableInView() { final WaitModel<Integer> mainModel = WaitModelLoader.Factory.waitOn(ResourceIds.raw.canonical); concurrency.loadUntilFirstFinish( GlideApp.with(context) .load(mainModel) .listener(requestListener) .thumbnail(GlideApp.with(context) .load(ResourceIds.raw.canonical) .listener(requestListener) .override(100, 100)), imageView); concurrency.runOnMainThread(new Runnable() { @Override public void run() { GlideApp.with(context).onStop(); } }); verify(requestListener, never()) .onResourceReady( anyDrawable(), any(), anyTarget(), eq(DataSource.DATA_DISK_CACHE), anyBoolean()); verify(requestListener, never()) .onResourceReady( anyDrawable(), any(), anyTarget(), eq(DataSource.RESOURCE_DISK_CACHE), anyBoolean()); assertThat(imageView.getDrawable()).isNull(); mainModel.countDown(); }
@Test public void clearDiskCache_doesNotPreventFutureLoads() throws ExecutionException, InterruptedException, TimeoutException { FutureTarget<Drawable> future = GlideApp.with(context) .load(ResourceIds.raw.canonical) .diskCacheStrategy(DiskCacheStrategy.DATA) .submit(IMAGE_SIZE_PIXELS, IMAGE_SIZE_PIXELS); concurrency.get(future); GlideApp.with(context).clear(future); clearMemoryCacheOnMainThread(); GlideApp.get(context).clearDiskCache(); future = GlideApp.with(context) .load(ResourceIds.raw.canonical) .diskCacheStrategy(DiskCacheStrategy.DATA) .submit(IMAGE_SIZE_PIXELS, IMAGE_SIZE_PIXELS); concurrency.get(future); GlideApp.with(context).clear(future); clearMemoryCacheOnMainThread(); concurrency.get( GlideApp.with(context) .load(ResourceIds.raw.canonical) .listener(requestListener) .diskCacheStrategy(DiskCacheStrategy.DATA) .submit(IMAGE_SIZE_PIXELS, IMAGE_SIZE_PIXELS)); verify(requestListener) .onResourceReady( anyDrawable(), any(), anyTarget(), eq(DataSource.DATA_DISK_CACHE), anyBoolean()); }
@Test public void testRequestListenerIsCalledWithIsFirstResourceIfNoRequestCoordinator() { harness.requestCoordinator = null; SingleRequest<List> request = harness.getRequest(); request.onResourceReady(harness.resource, DataSource.DATA_DISK_CACHE); verify(harness.requestListener) .onResourceReady(eq(harness.result), any(Number.class), isAListTarget(), isADataSource(), eq(true)); }
@Test public void testCacheIsCheckedIfMemoryCacheable() { when(harness.cache.remove(eq(harness.cacheKey))).thenReturn(harness.resource); harness.doLoad(); verify(harness.cb).onResourceReady(eq(harness.resource), eq(DataSource.MEMORY_CACHE)); }
@Test public void testRequestListenerIsCalledWithNotIsFirstRequestIfRequestCoordinatorReturnsResourceSet() { SingleRequest<List> request = harness.getRequest(); when(harness.requestCoordinator.isAnyResourceSet()).thenReturn(true); request.onResourceReady(harness.resource, DataSource.DATA_DISK_CACHE); verify(harness.requestListener) .onResourceReady(eq(harness.result), any(Number.class), isAListTarget(), isADataSource(), eq(false)); }
@Test public void testTargetIsCalledWithAnimationFromFactory() { SingleRequest<List> request = harness.getRequest(); Transition<List> transition = mockTransition(); when(harness.factory.build(any(DataSource.class), anyBoolean())).thenReturn(transition); request.onResourceReady(harness.resource, DataSource.DATA_DISK_CACHE); verify(harness.target).onResourceReady(eq(harness.result), eq(transition)); }
@Test public void testResourceOnlyReceivesOneGetOnResourceReady() { SingleRequest<List> request = harness.getRequest(); request.onResourceReady(harness.resource, DataSource.LOCAL); verify(harness.resource, times(1)).get(); }
@Override public void onDataFetcherFailed(Key attemptedKey, Exception e, DataFetcher<?> fetcher, DataSource dataSource) { fetcher.cleanup(); GlideException exception = new GlideException("Fetching data failed", e); exception.setLoggingDetails(attemptedKey, dataSource, fetcher.getDataClass()); throwables.add(exception); if (Thread.currentThread() != currentThread) { runReason = RunReason.SWITCH_TO_SOURCE_SERVICE; callback.reschedule(this); } else { runGenerators(); } }