此示例方法返回数字1到9的Observable<Integer>
:
public class Provider {
public static Observable<Integer> test() {
return Observable.create(SyncOnSubscribe.createStateless(new Action1<Observer<? super Integer>>() {
@Override
public void call(Observer<? super Integer> observer) {
for (int i = 1; i < 9; i++)
// when i == 2, throws IllegalStateException:
// "onNext called multiple times!":
observer.onNext(i);
}
}));
}
}
这只过滤1到9的倍数为3的数字:
public class RxJavaUnitTest {
@Test
public void rxJavaTest(){
List<Integer> multiplesOf3 = Provider.test().filter(new Func1<Integer, Boolean>() {
@Override
public Boolean call(Integer i) {
return i % 3 == 0;
}
}).toList().toBlocking().single();
}
}
但它会抛出IllegalStateException: “onNext called multiple times!”
。如果我不能多次拨打observer
,如何为onNext
提供更多价值?
也许SyncOnSubscribe.createStateless
在这里是错误的方法,并被其他东西取代?
答案 0 :(得分:4)
为什么不使用Observable.from
,
Observable.fromCallable
或Observable.defer
或类似的变体而不是Observable.create
?
但是你的答案是:
如SyncOnSubscribe.createStateless
Javadoc中所述:
...此重载会创建一个“无状态”的SyncOnSubscribe,它没有明确的状态值。当下一个函数关闭它的状态时,应该使用它。
这个Javadoc在这个问题上并不十分清楚,SyncOnSubscribe.next Javadoc可以找到更多:
...向下游用户呼叫
observer.onNext(t)
发送数据。要发出错误信号,请致电observer.onError(throwable)
或抛出Exception
。要通知数据流的结束,请致电observer.onCompleted()
。此方法的实现必须遵循以下规则。
- 每次调用不得超过
observer.onNext(t)
次。- 不得同时致电
observer.onNext(t)
。从此方法的调用返回的值将作为此方法的下一次调用的状态参数传入。
这意味着在回调操作中
onNext
应紧跟onCompleted
或onError
onNext
次调用 这对于在并发环境中强制执行安全性(这就是为什么称为 Sync
OnSubscribe
)和背压是必要的。 < / p>
可以在回调中考虑for循环:
return Observable.create(SyncOnSubscribe.createStateless(
new Action1<Observer<? super Integer>>() {
int counter = 0;
@Override
public void call(Observer<? super Integer> observer) {
if (counter < 9) {
observer.onNext(counter++);
} else {
observer.onCompleted();
}
}
}));
注意onCompleted
调用,否则,你的monad会永远运行。
这将生成以下列表{0, 3, 6}
。但代码很丑陋,违反了SyncOnSubscribe.createStateless
合同。 SyncOnSubscribe.createStateless
对无状态制作很有用,比如随机。相反,应该使用SyncOnSubscribe.createStateful
:
return Observable.create(SyncOnSubscribe.createStateful(
() -> 0,
(counter, observer) -> {
if (counter < 9) {
observer.onNext(counter);
} else {
observer.onCompleted();
}
return counter + 1;
}
));
然而,for循环仍然需要考虑因素,并且必须调用onCompleted
。