按可用元素的可用顺序组合可观察量

时间:2017-05-06 08:24:03

标签: java rx-java rx-java2

我正在尝试构建像s.startWith(x)这样的运算符,但是有条件的运算符 - 让我们称之为s.startWithIfNothingAvailable(x)。我希望仅当x 在订阅时{em>没有可用元素时,才会使用s为流添加前缀。

让我用一个例子说明这个想法。

s是来自服务器的报告流。

  • 如果还没有到达报告,我想在s前加一个空的 - 只是为了更新ui。
  • 如果s包含某些内容(可能会缓存某些报告),前缀s将导致呈现空报告,然后呈现非空报告。我想避免这种眨眼。

我认为解决问题的另一种方法是使用.concat之类的东西,但是可以通过其元素的可用性对可观察量进行排序。

Observable.concatFirstAvailable(serverReport, emptyReport),如果serverReport还没有元素 - 请切换到emptyReport,然后再回到等待serverReport

2 个答案:

答案 0 :(得分:1)

您可以合并延迟的特殊报告项目:

// imitate infinite hot service
PublishSubject<Report> service = PublishSubject.create();

// special report indicating the service has no reports
Report NO_REPORT = new Report();

AtomicBoolean hasValue = new AtomicBoolean();

service
// we'll need the main value for both emission and control message
.publish(main ->
     // this will keep "listening" to main and allow a timeout as well
     main.mergeWith(
         // signal the empty report indicator
         Observable.just(NO_REPORT)
         // after some grace period so main can emit a real report
         .delay(100, TimeUnit.MILLISECONDS)
         // but if the main emits first, don't signal the empty report
         .takeUntil(main)
     )
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(report -> {
     if (report == NO_REPORT) {
         // even if this onNext is serialized, NO_REPORT may get emitted
         if (!hasValue.get()) {
             // display empty report
         }
     } else {
         // this indicates a NO_REPORT should be ignored onward
         hasValue.set(true);
         // display normal report
     }
}, error -> {  /* show error */ })

Thread.sleep(200); // Thread.sleep(50)
service.onNext(new Report());

答案 1 :(得分:0)

如果我理解您的请求,那么您可以使用startWith()然后使用sample()

e.g。采样时间为50ms。如果没有报告在前50ms内到达,则将使用startWith元素并呈现空状态。否则,将使用最新报告。

Sample还会确保您不会经常更新您的用户界面:例如:当服务器在50ms内发送2个报告时,你不想同时渲染这两个报告,只是最新的报告。