From 2448962c58d789ece9015bf07b0b77cfa96c9d9c Mon Sep 17 00:00:00 2001 From: Dan Lew Date: Sat, 5 Sep 2015 08:52:06 -0500 Subject: [PATCH] Binding outside lifecycle causes instant completion Before, it would throw an exception, which doesn't make as much sense - if the logic worked out such that you bound outside the lifecycle, that prboably meant that you just don't want the subscription to occur outside the lifecycle, so it should end immediately. --- .../com/trello/rxlifecycle/RxLifecycle.java | 25 ++++++++++++++++--- .../trello/rxlifecycle/RxLifecycleTest.java | 18 +++++++------ 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/rxlifecycle/src/main/java/com/trello/rxlifecycle/RxLifecycle.java b/rxlifecycle/src/main/java/com/trello/rxlifecycle/RxLifecycle.java index 9317745..19593c5 100644 --- a/rxlifecycle/src/main/java/com/trello/rxlifecycle/RxLifecycle.java +++ b/rxlifecycle/src/main/java/com/trello/rxlifecycle/RxLifecycle.java @@ -15,11 +15,10 @@ package com.trello.rxlifecycle; import android.view.View; - import com.jakewharton.rxbinding.view.RxView; import com.jakewharton.rxbinding.view.ViewAttachEvent; - import rx.Observable; +import rx.exceptions.Exceptions; import rx.functions.Func1; import rx.functions.Func2; @@ -214,6 +213,17 @@ public Boolean call(R bindUntilEvent, R lifecycleEvent) { return lifecycleEvent == bindUntilEvent; } }) + .onErrorReturn(new Func1() { + @Override + public Boolean call(Throwable throwable) { + if (throwable instanceof OutsideLifecycleException) { + return true; + } + + Exceptions.propagate(throwable); + return false; + } + }) .takeFirst(new Func1() { @Override public Boolean call(Boolean shouldComplete) { @@ -246,7 +256,7 @@ public ActivityEvent call(ActivityEvent lastEvent) { case STOP: return ActivityEvent.DESTROY; case DESTROY: - throw new IllegalStateException("Cannot bind to Activity lifecycle when outside of it."); + throw new OutsideLifecycleException("Cannot bind to Activity lifecycle when outside of it."); default: throw new UnsupportedOperationException("Binding to " + lastEvent + " not yet implemented"); } @@ -282,10 +292,17 @@ public FragmentEvent call(FragmentEvent lastEvent) { case DESTROY: return FragmentEvent.DETACH; case DETACH: - throw new IllegalStateException("Cannot bind to Fragment lifecycle when outside of it."); + throw new OutsideLifecycleException("Cannot bind to Fragment lifecycle when outside of it."); default: throw new UnsupportedOperationException("Binding to " + lastEvent + " not yet implemented"); } } }; + + private static class OutsideLifecycleException extends IllegalStateException { + public OutsideLifecycleException(String detailMessage) { + super(detailMessage); + } + } + } diff --git a/rxlifecycle/src/test/java/com/trello/rxlifecycle/RxLifecycleTest.java b/rxlifecycle/src/test/java/com/trello/rxlifecycle/RxLifecycleTest.java index 2993f1b..e4f0ee8 100644 --- a/rxlifecycle/src/test/java/com/trello/rxlifecycle/RxLifecycleTest.java +++ b/rxlifecycle/src/test/java/com/trello/rxlifecycle/RxLifecycleTest.java @@ -16,22 +16,20 @@ import android.app.Activity; import android.view.View; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; - -import java.util.concurrent.CopyOnWriteArrayList; - import rx.Observable; import rx.Subscription; import rx.observers.TestSubscriber; import rx.subjects.BehaviorSubject; import rx.subjects.PublishSubject; +import java.util.concurrent.CopyOnWriteArrayList; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -137,13 +135,15 @@ public void testBindActivityLifecycle() { stopTestSub.assertUnsubscribed(); } - public void testThrowsExceptionOutsideActivityLifecycle() { + @Test + public void testEndsImmediatelyOutsideActivityLifecycle() { BehaviorSubject lifecycle = BehaviorSubject.create(); lifecycle.onNext(ActivityEvent.DESTROY); TestSubscriber testSubscriber = new TestSubscriber<>(); observable.compose(RxLifecycle.bindActivity(lifecycle)).subscribe(testSubscriber); - testSubscriber.assertError(IllegalStateException.class); + testSubscriber.assertCompleted(); + testSubscriber.assertUnsubscribed(); } @Test @@ -227,13 +227,15 @@ public void testBindFragmentLifecycle() { destroyTestSub.assertUnsubscribed(); } - public void testThrowsExceptionOutsideFragmentLifecycle() { + @Test + public void testEndsImmediatelyOutsideFragmentLifecycle() { BehaviorSubject lifecycle = BehaviorSubject.create(); lifecycle.onNext(FragmentEvent.DETACH); TestSubscriber testSubscriber = new TestSubscriber<>(); observable.compose(RxLifecycle.bindFragment(lifecycle)).subscribe(testSubscriber); - testSubscriber.assertError(IllegalStateException.class); + testSubscriber.assertCompleted(); + testSubscriber.assertUnsubscribed(); } @Test