如何在RxJava2中使用发布序列实现缓冲逻辑?

时间:2017-07-13 15:13:49

标签: android reactive-programming rx-java2

我想用RxJava实现以下目标,因为我可能没有足够的知识在这方面希望得到一些帮助:)

我需要创建一个PublishSubject,它将按以下顺序发出事件:

  • 发出1,2,3
  • 如果不满足某个条件,则订阅完成时缓冲区4(例如,可能是网络连接或某些其他条件)。
  • 如果条件不满足,则在4之后的5,6 ...缓冲区。
  • 在条件满足一段时间后重复发出4。
  • 如果尝试发射5,6并且条件满足,那么不​​要缓冲5,6 ......在4之后,只发出4然后5,6,7,8 ...

最后两点是必要的,因为发射顺序非常重要,这使我难以实现。

我希望我能描述一下我想要实现的目标:)

调查结果:在提出这个问题之后,我已经做了一些调查,并取得了以下成果:

private Observable observable = publishSubject
        .observeOn(Schedulers.io())
        .map(Manager::callNew)
        .doOnError(throwable -> Logger.e(throwable, "Error occurred"))
        .retryWhen(throwableObservable -> throwableObservable
                .zipWith(Observable.range(1, 10), (n, i) -> i)
                .flatMap(retryCount -> {
                    long retrySeconds = (long) Math.pow(2, retryCount);
                    Logger.d("The call has been failed retrying in %s seconds. Retry count %s", retrySeconds, retryCount);
                    return Observable.timer(retrySeconds, TimeUnit.SECONDS)
                            .doOnNext(aLong -> {
                                C24Logger.d("Timer was completed. %s", aLong);
                            })
                            .doOnComplete(() -> Logger.d("Timer was completed."));
                }));

问题在于PublishSubject。因为它已经发出了所有项目,所以它只发出新的重试时间。如果我使用ReplaySubject,它也会为新的重试发出旧的已完成的项目重新订阅时,我不再需要了。

有没有办法使用ReplaySubject从缓冲区中删除已完成的项目?

1 个答案:

答案 0 :(得分:0)

您希望能够根据外部条件打开和关闭缓冲。也许最简单的方法是使用buffer()运算符根据条件持续缓冲项目。

(我已经从观察链中删除了东西)

private Observable observable = publishSubject
      .publish( obs -> obs.buffer( obs.filter( v -> externalCondition( v ) ) ) )
      .flatMapIterable( bufferedList -> bufferedList )
      .subscribe( ... );

publish()运算符允许多个观察者链订阅传入的观察者链。 buffer()运算符监视仅在外部条件为真时才发出值的observable。

当外部条件为真时,buffer()将发出一系列仅包含单个元素的列表。当条件变为假时,buffer()开始缓冲结果,当条件再次变为真时,所有缓冲的项目都作为列表发出。 flatMapIterable()步骤将从缓冲区中取出每个项目并单独发出。