Observable.create(SyncOnSubscribe.createStateless(...))抛出IllegalStateException:“onNext多次调用!”

时间:2016-07-08 12:01:59

标签: java java-7 rx-java

此示例方法返回数字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在这里是错误的方法,并被其他东西取代?

1 个答案:

答案 0 :(得分:4)

为什么不使用Observable.fromObservable.fromCallableObservable.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应紧跟onCompletedonError
  • 并且每次回调调用只应该有一个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