我正在阅读http://www.introtorx.com/content/v1.0.10621.0/17_SequencesOfCoincidence.html#SequencesOfCoincidence并在那里找到关于window
运算符的以下部分:
“这些复杂重载中的第一个允许我们控制窗口何时关闭。每次创建窗口时都会调用windowClosingSelector函数。 Windows是在订阅时创建的,并在窗口关闭后立即创建;当windowClosingSelector的序列产生一个值时窗口关闭。该值被忽略,因此序列值的类型无关紧要;实际上你只需从windowClosingSelector完成序列就可以关闭窗口“
这似乎与public final <TClosing> Observable<Observable<T>> window(Func0<? extends Observable<? extends TClosing>> closingSelector)
方法文档和行为不同。我的测试显示产生闭合可观察量的Func0
只被调用一次,如上所述也没有完成这个可观察的工作 - 只创建了一个窗口。此方法实际上与public final <U> Observable<Observable<T>> window(Observable<U> boundary)
方法的工作方式相同,但边界直接传递而不是函数传递。从源代码判断,后者/更简单的方法只是通过将传递的边界包装到刚才返回的Func0中来调用前者/更复杂的方法。
问题:
看起来RxJava的public final <TClosing> Observable<Observable<T>> window(Func0<? extends Observable<? extends TClosing>> closingSelector)
的行为可能是错误的,除非该书是错误的或与RxJava兼容的Rx.NET的新版本发生了变化。这是Rx.NET和RxJava之间的故意不兼容吗?
如果不兼容性是正确的行为,为什么RxJava有两个window
重载实际上几乎相同?我没有看到使用函数创建窗口关闭observable的重载的任何明显优势,如果它不接受任何参数并且将被调用一次。好吧,它创建了可观察的懒惰,但我认为这可以通过defer
方法实现。
令人困惑的是,两个重载的大理石图略有不同(箭头是)。也许我只是不明白那里真正的区别?
buffer
方法存在相同的两个重载。
以下是一些代码,或多或少是上述文章中的一个端口。每行输入关闭当前并打开一个新窗口,除非它是'q'(不区分大小写),在这种情况下整个事情结束。
Observable<Long> source = Observable.interval(1L, TimeUnit.SECONDS);
PublishSubject<Object> closer = PublishSubject.create();
Subscription s = source
.window(() -> {
System.out.println("!!! creating window closer");
return closer;
})
.subscribe(new Subscriber<Observable<Long>>() {
private int idx = 0;
@Override
public void onNext(Observable<Long> window) {
++idx;
System.out.printf("+++ starting new window%n");
String windowName = "window " + idx;
window.subscribe(new Subscriber<Long>() {
@Override
public void onNext(Long aLong) {
System.out.printf("%s -> %d%n", windowName, aLong);
}
@Override
public void onError(Throwable e) {
// nothing
}
@Override
public void onCompleted() {
System.out.printf("--- %s completed%n", windowName);
}
});
}
@Override
public void onError(Throwable e) {
// nothing
}
@Override
public void onCompleted() {
System.out.println("completed");
}
});
Scanner scanner = new Scanner(System.in);
String input;
do {
input = scanner.nextLine();
closer.onNext(input);
//closer.onCompleted();
} while (!"q".equalsIgnoreCase(input));
s.unsubscribe();
用closer.onNext()
替换closer.onCompleted()
行打破了应用程序 - 只创建了一个窗口。
答案 0 :(得分:0)
正如所建议的那样,我在Github页面上提出了这个问题并修复了它:https://github.com/ReactiveX/RxJava/issues/3053。