我正在尝试构建像s.startWith(x)
这样的运算符,但是有条件的运算符 - 让我们称之为s.startWithIfNothingAvailable(x)
。我希望仅当x
在订阅时{em>没有可用元素时,才会使用s
为流添加前缀。
让我用一个例子说明这个想法。
s
是来自服务器的报告流。
s
前加一个空的 - 只是为了更新ui。 s
包含某些内容(可能会缓存某些报告),前缀s
将导致呈现空报告,然后呈现非空报告。我想避免这种眨眼。我认为解决问题的另一种方法是使用.concat
之类的东西,但是可以通过其元素的可用性对可观察量进行排序。
Observable.concatFirstAvailable(serverReport, emptyReport)
,如果serverReport
还没有元素 - 请切换到emptyReport
,然后再回到等待serverReport
。
答案 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个报告时,你不想同时渲染这两个报告,只是最新的报告。