@Test public void shouldRetryTwiceWithAirplaneModeOffAndNoNetworkInfo() { Action action = TestUtils.mockAction(URI_KEY_1, URI_1); PlatformLruCache cache = new PlatformLruCache(0); BitmapHunter hunter = new BitmapHunter(picasso, dispatcher, cache, stats, action, networkHandler); assertThat(hunter.shouldRetry(false, null)).isTrue(); assertThat(hunter.shouldRetry(false, null)).isTrue(); assertThat(hunter.shouldRetry(false, null)).isFalse(); }
@Test public void getPriorityAfterDetach() { Action action1 = mockAction(URI_KEY_1, URI_1, NORMAL); Action action2 = mockAction(URI_KEY_1, URI_1, HIGH); NetworkRequestHandler requestHandler = new NetworkRequestHandler(UNUSED_CALL_FACTORY, stats); BitmapHunter hunter = forRequest(mockPicasso(requestHandler), dispatcher, cache, stats, action1); hunter.attach(action2); assertThat(hunter.getAction()).isEqualTo(action1); assertThat(hunter.getActions()).containsExactly(action2); assertThat(hunter.getPriority()).isEqualTo(HIGH); hunter.detach(action2); assertThat(hunter.getAction()).isEqualTo(action1); assertThat(hunter.getActions()).isEmpty(); assertThat(hunter.getPriority()).isEqualTo(NORMAL); }
boolean loggingEnabled = hunter.getPicasso().loggingEnabled; Action single = hunter.getAction(); List<Action> joined = hunter.getActions(); boolean hasMultiple = joined != null && !joined.isEmpty(); hunter.detach(single); pausedActions.put(single.getTarget(), single); if (loggingEnabled) { hunter.detach(action); pausedActions.put(action.getTarget(), action); if (loggingEnabled) { if (hunter.cancel()) { it.remove(); if (loggingEnabled) {
private void markForReplay(BitmapHunter hunter) { Action action = hunter.getAction(); if (action != null) { markForReplay(action); } List<Action> joined = hunter.getActions(); if (joined != null) { //noinspection ForLoopReplaceableByForEach for (int i = 0, n = joined.size(); i < n; i++) { Action join = joined.get(i); markForReplay(join); } } }
void complete(BitmapHunter hunter) { Action single = hunter.getAction(); List<Action> joined = hunter.getActions(); boolean hasMultiple = joined != null && !joined.isEmpty(); boolean shouldDeliver = single != null || hasMultiple; if (!shouldDeliver) { return; } Uri uri = checkNotNull(hunter.getData().uri, "uri == null"); Exception exception = hunter.getException(); RequestHandler.Result result = hunter.getResult(); if (single != null) { deliverAction(result, single, exception); } if (joined != null) { //noinspection ForLoopReplaceableByForEach for (int i = 0, n = joined.size(); i < n; i++) { Action join = joined.get(i); deliverAction(result, join, exception); } } if (listener != null && exception != null) { listener.onImageLoadFailed(this, uri, exception); } }
static BitmapHunter mockHunter(String key, RequestHandler.Result result, Action action) { Request data = new Request.Builder(URI_1).build(); BitmapHunter hunter = mock(BitmapHunter.class); when(hunter.getKey()).thenReturn(key); when(hunter.getResult()).thenReturn(result); when(hunter.getData()).thenReturn(data); when(hunter.getAction()).thenReturn(action); Picasso picasso = mockPicasso(); when(hunter.getPicasso()).thenReturn(picasso); return hunter; }
@SuppressLint("MissingPermission") void performRetry(BitmapHunter hunter) { if (hunter.isCancelled()) return; if (hunter.shouldRetry(airplaneMode, networkInfo)) { if (hunter.getPicasso().loggingEnabled) { log(OWNER_DISPATCHER, VERB_RETRYING, getLogIdsForHunter(hunter)); if (hunter.getException() instanceof NetworkRequestHandler.ContentLengthException) { hunter.data = hunter.data.newBuilder().networkPolicy(NetworkPolicy.NO_CACHE).build(); performError(hunter); if (scansNetworkChanges && hunter.supportsReplay()) { markForReplay(hunter);
@Test public void cancelMultipleRequests() { Action action1 = mockAction(URI_KEY_1, URI_1, mockImageViewTarget()); Action action2 = mockAction(URI_KEY_1, URI_1, mockImageViewTarget()); BitmapHunter hunter = new TestableBitmapHunter(picasso, dispatcher, cache, stats, action1); hunter.future = new FutureTask<>(mock(Runnable.class), mock(Object.class)); hunter.attach(action2); assertThat(hunter.isCancelled()).isFalse(); assertThat(hunter.cancel()).isFalse(); hunter.detach(action1); hunter.detach(action2); assertThat(hunter.cancel()).isTrue(); assertThat(hunter.isCancelled()).isTrue(); }
@Test public void performCancelMultipleRequestsDetachesOnly() { Action action1 = mockAction(URI_KEY_1, URI_1); Action action2 = mockAction(URI_KEY_1, URI_1); BitmapHunter hunter = mockHunter(URI_KEY_1 + KEY_SEPARATOR, new RequestHandler.Result(bitmap1, MEMORY)); hunter.attach(action1); hunter.attach(action2); dispatcher.hunterMap.put(URI_KEY_1 + KEY_SEPARATOR, hunter); dispatcher.performCancel(action1); verify(hunter).detach(action1); verify(hunter).cancel(); assertThat(dispatcher.hunterMap).hasSize(1); }
@Test public void sequenceIsIncremented() { Action action = mockAction(URI_KEY_1, URI_1); Picasso picasso = mockPicasso(); BitmapHunter hunter1 = forRequest(picasso, dispatcher, cache, stats, action); BitmapHunter hunter2 = forRequest(picasso, dispatcher, cache, stats, action); assertThat(hunter2.sequence).isGreaterThan(hunter1.sequence); }
@Test public void cancelSingleRequest() { Action action1 = mockAction(URI_KEY_1, URI_1, mockImageViewTarget()); BitmapHunter hunter = new TestableBitmapHunter(picasso, dispatcher, cache, stats, action1); hunter.future = new FutureTask<>(mock(Runnable.class), mock(Object.class)); assertThat(hunter.isCancelled()).isFalse(); assertThat(hunter.cancel()).isFalse(); hunter.detach(action1); assertThat(hunter.cancel()).isTrue(); assertThat(hunter.isCancelled()).isTrue(); }
/** * Synchronously fulfill this request. Must not be called from the main thread. */ @Nullable // TODO make non-null and always throw? public Bitmap get() throws IOException { long started = System.nanoTime(); checkNotMain(); if (deferred) { throw new IllegalStateException("Fit cannot be used with get."); } if (!data.hasImage()) { return null; } Request request = createRequest(started); Action action = new GetAction(picasso, request); RequestHandler.Result result = forRequest(picasso, picasso.dispatcher, picasso.cache, picasso.stats, action).hunt(); Bitmap bitmap = result.getBitmap(); if (bitmap != null && shouldWriteToMemoryCache(request.memoryPolicy)) { picasso.cache.set(request.key, bitmap); } return bitmap; }
@Test public void outOfMemoryDispatchFailed() { Action action = mockAction(URI_KEY_1, URI_1); BitmapHunter hunter = new OOMBitmapHunter(picasso, dispatcher, cache, stats, action); hunter.run(); Exception exception = hunter.getException(); verify(dispatcher).dispatchFailed(hunter); assertThat(hunter.getResult()).isNull(); assertThat(exception).hasMessageThat().contains("BEGIN PICASSO STATS"); assertThat(exception.getCause()).isInstanceOf(OutOfMemoryError.class); }
@Test public void attachSingleRequest() { Action action1 = mockAction(URI_KEY_1, URI_1, mockImageViewTarget()); BitmapHunter hunter = new TestableBitmapHunter(picasso, dispatcher, cache, stats, action1); assertThat(hunter.action).isEqualTo(action1); hunter.detach(action1); hunter.attach(action1); assertThat(hunter.action).isEqualTo(action1); assertThat(hunter.actions).isNull(); }
void performCancel(Action action) { String key = action.request.key; BitmapHunter hunter = hunterMap.get(key); if (hunter != null) { hunter.detach(action); if (hunter.cancel()) { hunterMap.remove(key); if (action.picasso.loggingEnabled) { log(OWNER_DISPATCHER, VERB_CANCELED, action.request.logId()); } } } if (pausedTags.contains(action.getTag())) { pausedActions.remove(action.getTarget()); if (action.picasso.loggingEnabled) { log(OWNER_DISPATCHER, VERB_CANCELED, action.request.logId(), "because paused request got canceled"); } } Action remove = failedActions.remove(action.getTarget()); if (remove != null && remove.picasso.loggingEnabled) { log(OWNER_DISPATCHER, VERB_CANCELED, remove.request.logId(), "from replaying"); } }
void performSubmit(Action action, boolean dismissFailed) { if (pausedTags.contains(action.getTag())) { pausedActions.put(action.getTarget(), action); if (action.picasso.loggingEnabled) { log(OWNER_DISPATCHER, VERB_PAUSED, action.request.logId(), "because tag '" + action.getTag() + "' is paused"); } return; } BitmapHunter hunter = hunterMap.get(action.request.key); if (hunter != null) { hunter.attach(action); return; } if (service.isShutdown()) { if (action.picasso.loggingEnabled) { log(OWNER_DISPATCHER, VERB_IGNORED, action.request.logId(), "because shut down"); } return; } hunter = forRequest(action.picasso, this, cache, stats, action); hunter.future = service.submit(hunter); hunterMap.put(action.request.key, hunter); if (dismissFailed) { failedActions.remove(action.getTarget()); } if (action.picasso.loggingEnabled) { log(OWNER_DISPATCHER, VERB_ENQUEUED, action.request.logId()); } }
@Test public void completeInvokesErrorOnAllFailedRequests() { Action action1 = mockAction(URI_KEY_1, URI_1, mockImageViewTarget()); Action action2 = mockCanceledAction(); Exception exception = mock(Exception.class); BitmapHunter hunter = mockHunter(URI_KEY_1, null); when(hunter.getException()).thenReturn(exception); when(hunter.getActions()).thenReturn(Arrays.asList(action1, action2)); picasso.complete(hunter); verify(action1).error(exception); verify(action2, never()).error(exception); verify(listener).onImageLoadFailed(picasso, URI_1, exception); }
@Test public void performPauseOnlyDetachesPausedRequest() { Action action1 = mockAction(URI_KEY_1, URI_1, mockTarget(), "tag1"); Action action2 = mockAction(URI_KEY_1, URI_1, mockTarget(), "tag2"); BitmapHunter hunter = mockHunter(URI_KEY_1, new RequestHandler.Result(bitmap1, MEMORY)); when(hunter.getActions()).thenReturn(Arrays.asList(action1, action2)); dispatcher.hunterMap.put(URI_KEY_1, hunter); dispatcher.performPauseTag("tag1"); assertThat(dispatcher.hunterMap).hasSize(1); assertThat(dispatcher.hunterMap.containsValue(hunter)).isTrue(); assertThat(dispatcher.pausedActions).hasSize(1); assertThat(dispatcher.pausedActions.containsValue(action1)).isTrue(); verify(hunter).detach(action1); verify(hunter, never()).detach(action2); }
static BitmapHunter forRequest(Picasso picasso, Dispatcher dispatcher, PlatformLruCache cache, Stats stats, Action action) { Request request = action.request; List<RequestHandler> requestHandlers = picasso.getRequestHandlers(); // Index-based loop to avoid allocating an iterator. //noinspection ForLoopReplaceableByForEach for (int i = 0, count = requestHandlers.size(); i < count; i++) { RequestHandler requestHandler = requestHandlers.get(i); if (requestHandler.canHandleRequest(request)) { return new BitmapHunter(picasso, dispatcher, cache, stats, action, requestHandler); } } return new BitmapHunter(picasso, dispatcher, cache, stats, action, ERRORING_HANDLER); }
result = applyTransformations(picasso, data, transformations, result); bitmap = result.getBitmap(); if (bitmap != null) {