diff --git a/library/src/androidTest/java/com/bumptech/glide/request/target/ViewTargetTest.java b/library/src/androidTest/java/com/bumptech/glide/request/target/ViewTargetTest.java index ffa7a11484b5d4d36f51192fc2297e09725b2bc1..396457479ddc1504e004a1d39c962ce4ef0da059 100644 --- a/library/src/androidTest/java/com/bumptech/glide/request/target/ViewTargetTest.java +++ b/library/src/androidTest/java/com/bumptech/glide/request/target/ViewTargetTest.java @@ -27,10 +27,10 @@ import java.util.concurrent.CopyOnWriteArrayList; import static android.view.ViewGroup.LayoutParams; import static android.view.ViewTreeObserver.OnPreDrawListener; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasSize; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.inOrder; @@ -170,11 +170,51 @@ public class ViewTargetTest { } } - @Test(expected = IllegalArgumentException.class) - public void testThrowsIfCallbackIsQueuedTwice() { + @Test + public void testDoesNotNotifyCallbackTwiceIfAddedTwice() { SizeReadyCallback cb = mock(SizeReadyCallback.class); target.getSize(cb); target.getSize(cb); + + view.setLayoutParams(new LayoutParams(100, 100)); + + PreDrawShadowViewTreeObserver shadowObserver = Robolectric.shadowOf_(view.getViewTreeObserver()); + shadowObserver.fireOnPreDrawListeners(); + + verify(cb, times(1)).onSizeReady(anyInt(), anyInt()); + } + + @Test + public void testDoesNotAddMultipleListenersIfMultipleCallbacksAreAdded() { + SizeReadyCallback cb1 = mock(SizeReadyCallback.class); + SizeReadyCallback cb2 = mock(SizeReadyCallback.class); + target.getSize(cb1); + target.getSize(cb2); + + PreDrawShadowViewTreeObserver shadowObserver = Robolectric.shadowOf_(view.getViewTreeObserver()); + assertThat(shadowObserver.getPreDrawListeners(), hasSize(1)); + } + + @Test + public void testDoesAddSecondListenerIfFirstListenerIsRemovedBeforeSecondRequest() { + SizeReadyCallback cb1 = mock(SizeReadyCallback.class); + target.getSize(cb1); + + view.setLayoutParams(new LayoutParams(100, 100)); + + PreDrawShadowViewTreeObserver shadowObserver = Robolectric.shadowOf_(view.getViewTreeObserver()); + shadowObserver.fireOnPreDrawListeners(); + + assertThat(shadowObserver.getPreDrawListeners(), hasSize(0)); + + SizeReadyCallback cb2 = mock(SizeReadyCallback.class); + view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + target.getSize(cb2); + + view.setLayoutParams(new LayoutParams(100, 100)); + shadowObserver.fireOnPreDrawListeners(); + + verify(cb2).onSizeReady(anyInt(), anyInt()); } @Test diff --git a/library/src/main/java/com/bumptech/glide/request/target/ViewTarget.java b/library/src/main/java/com/bumptech/glide/request/target/ViewTarget.java index 7aa2a904af46e5981d023c33d714d191937859cf..cff57f7076a5853c78c5ea3e160b0f382baa5cc7 100644 --- a/library/src/main/java/com/bumptech/glide/request/target/ViewTarget.java +++ b/library/src/main/java/com/bumptech/glide/request/target/ViewTarget.java @@ -151,6 +151,7 @@ public abstract class ViewTarget extends BaseTarget { if (observer.isAlive()) { observer.removeOnPreDrawListener(layoutListener); } + layoutListener = null; } } @@ -172,13 +173,16 @@ public abstract class ViewTarget extends BaseTarget { } cb.onSizeReady(width, height); } else { - if (cbs.contains(cb)) { - throw new IllegalArgumentException("Cannot add a callback twice"); + // We want to notify callbacks in the order they were added and we only expect one or two callbacks to + // be added a time, so a List is a reasonable choice. + if (!cbs.contains(cb)) { + cbs.add(cb); + } + if (layoutListener == null) { + final ViewTreeObserver observer = view.getViewTreeObserver(); + layoutListener = new SizeDeterminerLayoutListener(this); + observer.addOnPreDrawListener(layoutListener); } - cbs.add(cb); - final ViewTreeObserver observer = view.getViewTreeObserver(); - layoutListener = new SizeDeterminerLayoutListener(this); - observer.addOnPreDrawListener(layoutListener); } }