@Override public Request getRequest() { return target.getRequest(); }
synchronized boolean untrack(@NonNull Target<?> target) { Request request = target.getRequest(); // If the Target doesn't have a request, it's already been cleared. if (request == null) { return true; } if (requestTracker.clearRemoveAndRecycle(request)) { targetTracker.untrack(target); target.setRequest(null); return true; } else { return false; } }
private void untrackOrDelegate(@NonNull Target<?> target) { boolean isOwnedByUs = untrack(target); // We'll end up here if the Target was cleared after the RequestManager that started the request // is destroyed. That can happen for at least two reasons: // 1. We call clear() on a background thread using something other than Application Context // RequestManager. // 2. The caller retains a reference to the RequestManager after the corresponding Activity or // Fragment is destroyed, starts a load with it, and then clears that load with a different // RequestManager. Callers seem especially likely to do this in retained Fragments (#2262). // // #1 is always an error. At best the caller is leaking memory briefly in something like an // AsyncTask. At worst the caller is leaking an Activity or Fragment for a sustained period of // time if they do something like reference the Activity RequestManager in a long lived // background thread or task. // // #2 is always an error. Callers shouldn't be starting new loads using RequestManagers after // the corresponding Activity or Fragment is destroyed because retaining any reference to the // RequestManager leaks memory. It's possible that there's some brief period of time during or // immediately after onDestroy where this is reasonable, but I can't think of why. if (!isOwnedByUs && !glide.removeFromManagers(target) && target.getRequest() != null) { Request request = target.getRequest(); target.setRequest(null); request.clear(); } }
@Test public void testRemovesPreviousRequestFromRequestTracker() { Request previous = mock(Request.class); when(target.getRequest()).thenReturn(previous); getNullModelRequest().into(target); verify(requestManager).clear(eq(target)); }
Request previous = target.getRequest(); if (request.isEquivalentTo(previous) && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
@Test public void removeFromManagers_afterRequestManagerRemoved_clearsRequest() { target = requestManager.load(mockUri("content://uri")).into(new SimpleTarget<Drawable>() { @Override public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) { // Do nothing. } }); Request request = Preconditions.checkNotNull(target.getRequest()); requestManager.onDestroy(); requestManager.clear(target); assertThat(target.getRequest()).isNull(); assertThat(request.isCleared()).isTrue(); }
@Override public Request getRequest() { return target.getRequest(); }
/** * Cancel any pending loads Glide may have for the target and free any resources (such as {@link Bitmap}s) that may * have been loaded for the target so they may be reused. * * @param target The Target to cancel loads for. */ public static void clear(Target<?> target) { Util.assertMainThread(); Request request = target.getRequest(); if (request != null) { request.clear(); target.setRequest(null); } }
/** * Set the target the resource will be loaded into. * * @see Glide#clear(Target) * * @param target The target to load the resource into. * @return The given target. */ public <Y extends Target<TranscodeType>> Y into(Y target) { Util.assertMainThread(); if (target == null) { throw new IllegalArgumentException("You must pass in a non null Target"); } if (!isModelSet) { throw new IllegalArgumentException("You must first set a model (try #load())"); } Request previous = target.getRequest(); if (previous != null) { previous.clear(); requestTracker.removeRequest(previous); previous.recycle(); } Request request = buildRequest(target); target.setRequest(request); lifecycle.addListener(target); requestTracker.runRequest(request); return target; }
@Override public Request getRequest() { return target.getRequest(); }
@Override public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) { Log.w(TAG, "onException: ", e); Log.d(TAG, "onException: " + model); Log.d(TAG, "onException: " + target.getRequest().isRunning()); return false; }
boolean untrack(Target<?> target) { Request request = target.getRequest(); // If the Target doesn't have a request, it's already been cleared. if (request == null) { return true; } if (requestTracker.clearRemoveAndRecycle(request)) { targetTracker.untrack(target); target.setRequest(null); return true; } else { return false; } }
private <Y extends Target<TranscodeType>> Y into(@NonNull Y target, RequestOptions options) { Util.assertMainThread(); Preconditions.checkNotNull(target); if (!isModelSet) { throw new IllegalArgumentException("You must call #load() before calling #into()"); } options = options.autoClone(); Request request = buildRequest(target, options); Request previous = target.getRequest(); if (request.isEquivalentTo(previous)) { request.recycle(); // If the request is completed, beginning again will ensure the result is re-delivered, // triggering RequestListeners and Targets. If the request is failed, beginning again will // restart the request, giving it another chance to complete. If the request is already // running, we can let it continue running without interruption. if (!Preconditions.checkNotNull(previous).isRunning()) { previous.begin(); } return target; } requestManager.clear(target); target.setRequest(request); requestManager.track(target, request); return target; }