“暂停后第一次”重新启动的RX示例

时间:2017-06-10 14:37:17

标签: rx-java

有人可以建议如何用rx java实现这个案例吗? enter image description here

看起来像sample,但有两点不同:

  1. 样本以第一次发射开始( 1 ),即使之前订阅过。
  2. 如果两个发射之间的间隔(本示例中 4 5 )超过采样率(1秒),则样本将在后一个发射时重新开始( 5 )。

1 个答案:

答案 0 :(得分:1)

这需要一个自定义操作符(可靠)或与现有操作符组合(不太可靠):

public static void main(String[] args) throws Exception {
    int[] delay = { 0, 100, 250, 300, 900, 975, 1050, 1200 };

    Flowable.range(0, delay.length)
    .flatMap(v -> Flowable.timer(delay[v], TimeUnit.MILLISECONDS)
        .map(u -> (v + 1) + " @ " + delay[v] + " ms"))
    .compose(firstAndSample(200, TimeUnit.MILLISECONDS))
    .blockingSubscribe(System.out::println)
    ;
}

public static <T> FlowableTransformer<T, T> firstAndSample(long delay, TimeUnit unit) {
    return f -> {
        Scheduler s = new SingleScheduler();
        return f.publish(g -> {
           return g.take(1)
           .concatWith(
               g
               .sample(delay, unit, s, true)
               .timeout(delay + 1, unit, s)
           )
           .retry(e -> e instanceof TimeoutException)
           ;
        });
    };
}

它通过上游(publish)的共享流中的相位切换来工作。在第一阶段,从上游获取1项,然后切换到第2阶段(concatWith)。第二阶段对上游(sample)进行采样,如果采样在其周期(timeout)之后没有发出任何内容,则它会使子流失败,我们再次通过重试切换到阶段1 TimeoutException已触发。为了确保按顺序进行采样和超时评估,两者都使用特定的单线程Scheduler。 (可靠性较低来自相变并非原子,因为其组件在多个运算符之间分配)。