简体   繁体   English

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

[英]How to achieve buffering logic with publish sequence in RxJava2?

I want to achieve the following with RxJava and as I may not have enough knowledge in this area would like to have some help :) 我想用RxJava实现以下目标,因为我可能没有足够的知识在这方面希望得到一些帮助:)

I need to create a PublishSubject which would emit events with the following sequence: 我需要创建一个PublishSubject,它将按以下顺序发出事件:

  • Emit 1, 2, 3 发出1,2,3
  • Buffer 4 in subscribe's completion if a certain condition is not satisfied (may be a network connection for example or some other condition). 如果不满足某个条件,则订阅完成时缓冲区4(例如,可以是网络连接或某些其他条件)。
  • For 5, 6 ... buffer after 4 if the condition is not satisfied yet. 如果条件不满足,则在4之后的5,6 ...缓冲区。
  • Repeat to emit 4 after some time when the condition is satisfied. 在条件满足一段时间后重复发出4。
  • If trying to emit 5,6 and the condition is satisfied, then instead of buffering 5, 6 ... after 4, just emit 4 and then 5, 6, 7 , 8 ... 如果试图发射5,6并且条件满足,那么不​​是缓冲5,6 ......在4之后,只发射4然后5,6,7,8 ......

The last 2 points are necessary because the sequence of emitting is really important, which makes difficulties for me to achieve to this. 最后2点是必要的,因为发射顺序非常重要,这使我难以实现。

I hope I could describe what I want to achieve :) 我希望我能描述一下我想要实现的目标:)

Findings: After asking this question I've done some findings and achieved the following: 调查结果:在提出这个问题之后,我做了一些调查,并取得了以下成果:

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."));
                }));

The problem is here with PublishSubject. 问题在于PublishSubject。 Because it already has emitted all the items, it emits only new ones for retryWhen. 因为它已经发出了所有项目,所以它只发出新的重试时间。 If I use ReplaySubject them it emits also the old completed items too for the new retryWhen re-subscribe, which I do not need anymore. 如果我使用ReplaySubject,它也会为新重试发出旧的已完成项目,当重新订阅时,我不再需要它了。

Is there a way to use the ReplaySubject to remove the completed items from the buffer? 有没有办法使用ReplaySubject从缓冲区中删除已完成的项目?

You want to be able to turn buffering on and off, depending upon an external condition. 您希望能够根据外部条件打开和关闭缓冲。 Perhaps the simplest way to do it is use the buffer() operator to continually buffer items based on the condition. 也许最简单的方法是使用buffer()运算符根据条件持续缓冲项目。

(I have removed stuff from the observer chain) (我从观察链中删除了东西)

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

The publish() operator allows multiple observer chains to subscribe to the incoming observer chain. publish()运算符允许多个观察者链订阅传入的观察者链。 The buffer() operator monitors the observable that emits a value only when the external condition is true. buffer()运算符监视仅在外部条件为真时才发出值的observable。

When the external condition is true, buffer() will emit a series of lists with only a single element. 当外部条件为真时, buffer()将发出一系列仅包含单个元素的列表。 When the condition goes false, buffer() starts buffering up the results, and when the condition goes true again, all the buffered items are emitted as a list. 当条件变为false时, buffer()开始缓冲结果,当条件再次变为true时,所有缓冲的项都作为列表发出。 The flatMapIterable() step will take each item out of the buffer and emit it separately. flatMapIterable()步骤将每个项目从缓冲区中取出并单独发出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM