RxJava的扫描操作员可以在多个订户之间保持状态

时间:2017-10-29 11:27:06

标签: java rx-java

我有一个observable,它使用scan运算符进行转换,因此它总是根据当前值和前一个值(或初始值)发出一个值。

Subject<String> subject = PublishSubject.create();
Observable<String> observable = subject.scan("zero", (a, b) -> a + ", " + b);

然后,第一个观察者订阅,打印所有发出的值,并在一段时间后取消订阅。

Disposable first = observable.subscribe(System.out::println); // "zero"
subject.onNext("one"); // "zero, one"
first.dispose();

稍后,另一位订阅者订阅:

Disposable second = observable.subscribe(System.out::println); // "zero"
subject.onNext("two"); // "zero, one"
second.dispose();

正如您所看到的,每个观察者首先被提供初始值,并且在订阅前一个时发出的值消失了。我想要实现的是将scan运算符中的状态保留在所有订阅中:

Disposable first = observable.subscribe(System.out::println); // "zero"
subject.onNext("one"); // "zero, one"
first.dispose();
Disposable second = observable.subscribe(System.out::println); // "zero, one"
subject.onNext("two"); // "zero, one, two"
second.dispose();

RxJava中是否有解决此问题的方法?

3 个答案:

答案 0 :(得分:1)

我通过引入BehaviorSubject作为“缓存”层找到了解决方案。不确定这是否是解决问题的最简洁方法,但它确实有效。

该行:

Observable<String> observable = subject.scan("zero", (a, b) -> a + ", " + b);

必须转变为:

Subject<String> observable = BehaviorSubject.create();
subject.scan("zero", (a, b) -> a + ", " + b)
       .subscribe(observable);

答案 1 :(得分:1)

您可以扫描到BehaviorSubject,其他人应该订阅:

Subject<String> subject = PublishSubject.create();
Observable<String> observable = subject.scan("zero", (a, b) -> a + ", " + b);
Subject<String> multicast = BehaviorSubject.create();

observable.subscribe(multicast);

Disposable first = multicast.subscribe(System.out::println); // "zero"
subject.onNext("one"); // "zero, one"
first.dispose();
Disposable second = multicast.subscribe(System.out::println); // "zero, one"
subject.onNext("two"); // "zero, one, two"
second.dispose();

答案 2 :(得分:1)

另一种解决方案:

observable#publish会将结果多播到所有订阅者,因此会保留最后的#scan值。您的解决方案无效,因为每次订阅时都会创建一个新的Observable。扫描值未保留。

@Test
void name3231() {
    Subject<String> subject = PublishSubject.create();
    Observable<String> observable = subject.scan("zero", (a, b) -> a + ", " + b);

    ConnectableObservable<String> observableMulticast = observable.publish();

    Disposable connect = observableMulticast.connect(); // must be disposed by hand

    TestObserver<String> test = observableMulticast.test();

    Disposable first = observableMulticast.subscribe(System.out::println); // "zero"
    subject.onNext("one"); // "zero, one"
    first.dispose();

    test.assertValues("zero, one");

    Disposable second = observableMulticast.subscribe(System.out::println); // "zero, one"
    subject.onNext("two"); // "zero, one, two"
    second.dispose();

    test.assertValues("zero, one", "zero, one, two");
}