简体   繁体   English

RxJava:缓冲项目,直到当前项目的某些条件为真

[英]RxJava: buffer items until some condition is true for current item

Here's a snippet I'm trying to figure out: 这是我想弄清楚的一个片段:

class RaceCondition {

    Subject<Integer, Integer> subject = PublishSubject.create();

    public void entryPoint(Integer data) {
        subject.onNext(data);
    }

    public void client() {
        subject /*some operations*/
                .buffer(getClosingSelector())
                .subscribe(/*handle results*/);
    }

    private Observable<Integer> getClosingSelector() {
        return subject /* some filtering */;
    }
}

There's a Subject that accepts events from the outside. 有一个Subject接受来自外部的事件。 There's a client subscribed to this subject that processes the events and also buffer s them. 有一个客户订阅了这个主题,它处理事件并buffer它们。 The main idea here is that the buffered items should be emitted each time based on some condition calculated using an item from the stream. 这里的主要思想是每次都应该根据使用流中的项计算的某些条件来发出缓冲的项。

For this purpose the buffer boundary itself listens to the subject. 为此,缓冲区边界本身监听主题。

An important desired behaviour: whenever the boundary emits the item, it should also be included in the following emission of the buffer . 一个重要的期望行为:每当边界发出项目时,它也应该包含在buffer的以下发射中。 It's not the case with the current configuration as the item (at least that's what I think) is emitted from the closing selector before it reaches the buffer , so that it's not included in the current emission but is left behind waiting for the next one. 当前配置不是这样的项目(至少我认为是这样)在关闭选择器到达buffer 之前从关闭选择器发出,因此它不包含在当前发射中但是等待下一个发射。

Is there a way to essentially make closing selector wait for the item to be buffered first? 有没有办法基本上使关闭选择器等待项目首先被缓冲? If not, is there another way to buffer and release items based on the next incoming item? 如果没有,是否有另一种方法来缓冲和释放基于下一个传入项目的项目?

If I understand correctly, you want to buffer until some predicate allows it based on the items. 如果我理解正确,你想要缓冲,直到一些谓词允许它基于项目。 You can do this with a complicated set of operators but perhaps its easier to just write a custom operator: 您可以使用一组复杂的运算符来完成此操作,但可能更容易编写自定义运算符:

public final class BufferUntil<T> 
implements Operator<List<T>, T>{

    final Func1<T, Boolean> boundaryPredicate;

    public BufferUntil(Func1<T, Boolean> boundaryPredicate) {
        this.boundaryPredicate = boundaryPredicate;
    }

    @Override
    public Subscriber<? super T> call(
            Subscriber<? super List<T>> child) {
        BufferWhileSubscriber parent = 
                new BufferWhileSubscriber(child);
        child.add(parent);
        return parent;
    }

    final class BufferWhileSubscriber extends Subscriber<T> {
        final Subscriber<? super List<T>> actual;

        List<T> buffer = new ArrayList<>();

        /**
         * @param actual
         */
        public BufferWhileSubscriber(
                Subscriber<? super List<T>> actual) {
            this.actual = actual;
        }

        @Override
        public void onNext(T t) {
            buffer.add(t);
            if (boundaryPredicate.call(t)) {
                actual.onNext(buffer);
                buffer = new ArrayList<>();
            }
        }

        @Override
        public void onError(Throwable e) {
            buffer = null;
            actual.onError(e);
        }

        @Override
        public void onCompleted() {
            List<T> b = buffer;
            buffer = null;
            if (!b.isEmpty()) {
                actual.onNext(b);
            }
            actual.onCompleted();
        }
    }
}

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

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