Rx java RxJava:如何将不稳定的事件源转换为更频繁的进展源?

Rx java RxJava:如何将不稳定的事件源转换为更频繁的进展源?,rx-java,Rx Java,我有一个可观察的(RxJava 1.x),随机发生事件: int numberOfItems = 10; Observable<Integer> unsteadyEvents = Observable.range(1, numberOfItems) .concatMap(progress -> Observable.just(progress)

我有一个可观察的(RxJava 1.x),随机发生事件:

    int numberOfItems = 10;
    Observable<Integer> unsteadyEvents = Observable.range(1, numberOfItems)
            .concatMap(progress ->
                    Observable.just(progress)
                            .delay(ThreadLocalRandom.current().nextInt(4), TimeUnit.SECONDS)
            );
    Stopwatch stopwatch = Stopwatch.createStarted();
    unsteadyEvents
            .map(progress -> "Progress " + progress + "/" + numberOfItems + " after " + stopwatch)
            .subscribe(System.out::println, Throwable::printStackTrace, () -> System.out.println("Done."));
对于GUI,我希望至少每秒有一个更频繁的进度事件的输出:

Progress 0/10 after 1 s
Progress 0/10 after 2 s
Progress 0/10 after 3 s 
Progress 1/10 after 3.067 s
Progress 2/10 after 3.085 s
Progress 2/10 after 4 s
Progress 2/10 after 5 s
Progress 3/10 after 5.095 s
Progress 3/10 after 6 s
Progress 4/10 after 6.109 s
Progress 5/10 after 6.110 s
Progress 5/10 after 7 s
Progress 6/10 after 7.124 s
Progress 6/10 after 8 s
Progress 6/10 after 9 s
Progress 7/10 after 9.136 s
Progress 7/10 after 10 s
Progress 7/10 after 11 s
Progress 7/10 after 12 s
Progress 8/10 after 12.15 s
Progress 9/10 after 12.15 s
Progress 10/10 after 12.15 s
Done.
其思想是,即使没有“真正的进展”,用户也可以在GUI中看到一个更新,其中包含来自秒表的新值

问题:我如何将不稳定的事件源转化为更频繁的进步源


提示:我在寻找某种“组合”魔法,而不是将“实际进度”和“秒表事件”拆分为两个单独的可观察对象。

您可以使用
withLatestFrom()
操作符来协调两个可观察对象

Observable.interval( 1, TimeUnit.MILLISECONDS )
  .withLatestFrom( sourceOfSporadicUpdates, ( tick, update ) -> update )

这将为您的GUI提供一系列定期更新,其中包含最新的进度值。

由于
interval
永远不会结束,您可以
将两者都具体化,以便您的不稳定流触发完成:

Observable.combineLatest(
  unsteadyEvents.materialize(),
  Observable.interval(0, 1, TimeUnit.SECONDS).materialize(),
  (tick, update) -> update
)
              .dematerialize();

[de]物化
onNext
onError
onComplete
包装和打开标准事件对象中的项目。这里的关键是
interval
应该只发出
onNext
,这样您就可以保留
不稳定事件中所有感兴趣的事件

谢谢你的努力,鲍勃。我觉得没那么容易。。。您的解决方案有两个问题:1)可观察的永远不会完成2)“实际进度”事件有时会被跳过。试一试。谢谢你使用materialize/dematerialize的好“技巧”!Observable#CombineTest是RxJava1.x中的一种静态方法。您的示例无法编译。你能更新这个例子吗?我试图自己更新它,但我的编辑在同行评议中被放弃了。谢谢
Observable.combineLatest(
  unsteadyEvents.materialize(),
  Observable.interval(0, 1, TimeUnit.SECONDS).materialize(),
  (tick, update) -> update
)
              .dematerialize();