repeatWhen基于触发完成的事件

时间:2016-11-01 13:53:52

标签: rx-java

我已经获得以下代码来修改我的源observable,以便在应用程序状态在ENABLED和DISABLED之间切换时断开连接并重新连接。

但是,如果我的sourceObservable本身有一个调用完成的情况,我怀疑它会立即重新连接,因为这个变换器会重复,如果应用程序状态仍然是ENABLED。

是否有一种优雅的解决方法,可能将takeUntil和repeatWhen分组,以便它们不会捕获来自上方的任何完整事件?

N.B。 applicationStatusObservable根据请求重复其最后一个值。

非常感谢帮助:)

/**
 * Transforms the source observable so that it defers initial subscription until the service becomes available,
 * unsubscribes when the service becomes unavailable, and resubscribes when the service becomes available again.
 */
public class AvailabilityTransformer<T> implements Observable.Transformer<T, T> {

    private final Observable<ApplicationStatus> applicationStatusObservable;

    AvailabilityTransformer(final Observable<ApplicationStatus> applicationStatusObservable) {
        this.applicationStatusObservable = applicationStatusObservable;
    }

    @Override
    public Observable<T> call(final Observable<T> sourceObservable) {
        final Observable<ApplicationStatus> applicationEnabledObservable =
                applicationStatusObservable.filter(applicationStatus -> applicationStatus == ENABLED);
        final Observable<ApplicationStatus> applicationDisabledObservable =
                applicationStatusObservable.filter(applicationStatus -> applicationStatus != ENABLED);
        return sourceObservable
                .takeUntil(applicationDisabledObservable) // Unsubscribe whenever the application is disabled
                .repeatWhen(repeatObservable -> repeatObservable.flatMap(repeat ->
                        applicationEnabledObservable.flatMap(applicationStatus -> just(repeat)))) // Resubscribe when enabled again
                .delaySubscription(applicationEnabledObservable.first()); // Delay the initial subscription until the application is first enabled
    }
}

1 个答案:

答案 0 :(得分:0)

他,

我花了一些时间来了解你在做什么。我希望我终于明白了。您有一个热的observable isApplicationAvailable,它将告诉订阅者应用程序是启用还是禁用(true / false)。你有其他的observable,它们正在做一些工作(可能是热/冷)并希望它们只产生值,如果observable isApplicationAvailable返回true。如果某些reaseon应用程序被禁用,则observables不应生成任何值。

我使用RxJava2进行测试。

在此示例中,如果observable isApplicationActive返回true,stringObservable将仅将值传递给订阅者。

@Test
public void name() throws Exception {
    Subject<Boolean> isApplicationActive = BehaviorSubject.<Boolean>create()
            .toSerialized();

    Observable<Boolean> isApplicationActiveObservable = isApplicationActive
            .hide()
            .doOnNext(s -> System.out.println("isApplicationActive: " + s));

    isApplicationActive.onNext(false);

    Thread.sleep(1_000);

    Observable<String> stringObservable = Observable.interval(1_000, TimeUnit.MILLISECONDS)
            .map(Objects::toString)
            .doOnNext(s -> System.out.println("NextIntervalValue"))
            .compose(createSwitchMapCompose(isApplicationActiveObservable));

    stringObservable.subscribe(s -> {
        System.out.println("stringObservable: " + s);
    });

    Thread.sleep(2_000);

    isApplicationActive.onNext(true);

    Thread.sleep(2_000);

    isApplicationActive.onNext(false);

    Thread.sleep(2_000);

    isApplicationActive.onNext(true);

    Thread.sleep(6_000);

    isApplicationActive.onNext(false);

    Thread.sleep(20_000);
}

private ObservableTransformer<String, String> createSwitchMapCompose(Observable<Boolean> isApplicationActiveObservable) {
    return upstream -> upstream.switchMap(s -> isApplicationActiveObservable.take(1).flatMap(aBoolean -> {
                if (aBoolean) {
                    return Observable.just(s);
                }
                return Observable.empty();
            })
    );
}