diff --git a/library/src/androidTest/java/com/bumptech/glide/load/engine/SourceResourceRunnerTest.java b/library/src/androidTest/java/com/bumptech/glide/load/engine/SourceResourceRunnerTest.java index b206442b57478d572931754c8839212960bdf9e2..7963caad05709d149dc65e21d3ec78958977ed53 100644 --- a/library/src/androidTest/java/com/bumptech/glide/load/engine/SourceResourceRunnerTest.java +++ b/library/src/androidTest/java/com/bumptech/glide/load/engine/SourceResourceRunnerTest.java @@ -33,6 +33,7 @@ import static org.mockito.Matchers.isNull; import static org.mockito.Mockito.doAnswer; 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; @@ -420,6 +421,14 @@ public class SourceResourceRunnerTest { verify(harness.cb).onException(exception); } + @Test + public void testNotifiesJobOfFailureOnlyOnce() throws Exception { + when(harness.fetcher.loadData(any(Priority.class))).thenThrow(new IOException("test")); + harness.getRunner().run(); + + verify(harness.cb, times(1)).onException(any(Exception.class)); + } + @SuppressWarnings("unchecked") private static class SourceResourceHarness { CacheLoader cacheLoader = mock(CacheLoader.class); diff --git a/library/src/main/java/com/bumptech/glide/Glide.java b/library/src/main/java/com/bumptech/glide/Glide.java index 1c3cd0c65ac7e38efea2a9959b6e63f9a8e15ca2..3c9b503ce52bf67dd44cf5b007aaaa1feb3ebc1f 100644 --- a/library/src/main/java/com/bumptech/glide/Glide.java +++ b/library/src/main/java/com/bumptech/glide/Glide.java @@ -59,6 +59,7 @@ import com.bumptech.glide.request.animation.GlideAnimation; import com.bumptech.glide.request.target.ImageViewTargetFactory; import com.bumptech.glide.request.target.Target; import com.bumptech.glide.request.target.ViewTarget; +import com.bumptech.glide.util.Util; import java.io.File; import java.io.InputStream; @@ -332,6 +333,7 @@ public class Glide { * @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(); diff --git a/library/src/main/java/com/bumptech/glide/load/engine/EngineJob.java b/library/src/main/java/com/bumptech/glide/load/engine/EngineJob.java index c1ffa6ff925230c9780843be887db616c76e64bf..1dd7739811fedf7abecd397df0bc4ff639341917 100644 --- a/library/src/main/java/com/bumptech/glide/load/engine/EngineJob.java +++ b/library/src/main/java/com/bumptech/glide/load/engine/EngineJob.java @@ -5,6 +5,7 @@ import android.util.Log; import com.bumptech.glide.load.Key; import com.bumptech.glide.request.ResourceCallback; import com.bumptech.glide.util.LogTime; +import com.bumptech.glide.util.Util; import java.util.ArrayList; import java.util.List; @@ -15,12 +16,14 @@ import java.util.List; */ class EngineJob implements ResourceCallback { private static final String TAG = "EngineJob"; - private boolean isCacheable; + + private final List cbs = new ArrayList(); + private final EngineJobListener listener; - private Key key; - private Handler mainHandler; - private List cbs; - private ResourceCallback cb; + private final Key key; + private final Handler mainHandler; + private final boolean isCacheable; + private boolean isCancelled; private boolean isComplete; @@ -32,25 +35,14 @@ class EngineJob implements ResourceCallback { } public void addCallback(ResourceCallback cb) { - if (this.cb == null) { - this.cb = cb; - } else { - if (cbs == null) { - cbs = new ArrayList(2); - cbs.add(this.cb); - } - cbs.add(cb); - } + Util.assertMainThread(); + cbs.add(cb); } public void removeCallback(ResourceCallback cb) { - if (cbs != null) { - cbs.remove(cb); - if (cbs.size() == 0) { - cancel(); - } - } else if (this.cb == cb) { - this.cb = null; + Util.assertMainThread(); + cbs.remove(cb); + if (cbs.isEmpty()) { cancel(); } } @@ -82,6 +74,8 @@ class EngineJob implements ResourceCallback { if (isCancelled) { resource.recycle(); return; + } else if (cbs.isEmpty()) { + throw new IllegalStateException("Received a resource without any callbacks to notify"); } resource.setCacheable(isCacheable); isComplete = true; @@ -90,13 +84,8 @@ class EngineJob implements ResourceCallback { // synchronously released by one of the callbacks. resource.acquire(1); listener.onEngineJobComplete(key, resource); - if (cbs != null) { - resource.acquire(cbs.size()); - for (ResourceCallback cb : cbs) { - cb.onResourceReady(resource); - } - } else { - resource.acquire(1); + resource.acquire(cbs.size()); + for (ResourceCallback cb : cbs) { cb.onResourceReady(resource); } // Our request is complete, so we can release the resource. @@ -120,15 +109,14 @@ class EngineJob implements ResourceCallback { } if (isCancelled) { return; + } else if (cbs.isEmpty()) { + throw new IllegalStateException("Received an exception without any callbacks to notify"); } + isComplete = true; listener.onEngineJobComplete(key, null); - if (cbs != null) { - for (ResourceCallback cb : cbs) { - cb.onException(e); - } - } else { + for (ResourceCallback cb : cbs) { cb.onException(e); } if (Log.isLoggable(TAG, Log.VERBOSE)) { diff --git a/library/src/main/java/com/bumptech/glide/load/engine/SourceResourceRunner.java b/library/src/main/java/com/bumptech/glide/load/engine/SourceResourceRunner.java index 8a77906e290465c9fc9f5404c7420941afc2a180..4dd613d5580f9a89c86fede7a10ad25332e932a5 100644 --- a/library/src/main/java/com/bumptech/glide/load/engine/SourceResourceRunner.java +++ b/library/src/main/java/com/bumptech/glide/load/engine/SourceResourceRunner.java @@ -118,17 +118,18 @@ class SourceResourceRunner implements Runnable, Prioritized { return; } - Resource result = null; + final Resource result; try { result = runWrapped(); } catch (Exception e) { cb.onException(e); + return; } - if (result == null) { - cb.onException(null); - } else { + if (result != null) { cb.onResourceReady(result); + } else { + cb.onException(null); } } diff --git a/library/src/main/java/com/bumptech/glide/request/GenericRequest.java b/library/src/main/java/com/bumptech/glide/request/GenericRequest.java index cc79916cc6ec3f80ce13f3133d460600b334a8f4..cf1490b0769cadeffa3877068769192f71f6468e 100644 --- a/library/src/main/java/com/bumptech/glide/request/GenericRequest.java +++ b/library/src/main/java/com/bumptech/glide/request/GenericRequest.java @@ -21,6 +21,7 @@ import com.bumptech.glide.request.animation.GlideAnimationFactory; import com.bumptech.glide.request.target.SizeReadyCallback; import com.bumptech.glide.request.target.Target; import com.bumptech.glide.util.LogTime; +import com.bumptech.glide.util.Util; import java.io.File; import java.util.ArrayDeque; @@ -276,6 +277,7 @@ public final class GenericRequest implements Request, SizeReadyCallb */ @Override public void clear() { + Util.assertMainThread(); cancel(); // Resource must be released before canNotifyStatusChanged is called. if (resource != null) {