我使用combinateLatest()来组合3个可观察值流。将所有这些组合在一起,以便同时显示UI中的所有数据。现在,存在一种情况,其中可观察对象之一将不会发出任何东西,因为获取的数据可能为空。
是否有RxJava运算符让订户知道由于空数据而不会产生任何发射?
修改
private fun retrieveData() {
Observable.combineLatest(getCurrentUser.execute(), getLatestGoal.execute(), getLatestLog.execute(),
Function3<User, Goal, Log, PersonalViewModel> { user, goal, log -> mapToViewModel(user, goal, log) })
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe { /*todo: animation*/ }
.doOnNext { view.setViewModel(it) }
.doOnComplete { view.stopLoading() }
.doOnError { /*todo: error message*/ }
.subscribe()
}
第三个流:当用户拥有nog日志时,getLatestLog.execute()不发出任何内容。当此流不发出时,整个视图将不可见。
从FireBase Realtime数据库中获取数据。 ChildEventListener具有如下所示的方法:
override fun onChildAdded(dataSnapshot: DataSnapshot?, p1: String?) {
val log = dataSnapshot?.getValue(Log::class.java)
log?.let { subscriber.onNext(it) }
subscriber.onComplete()
firebaseDatabase.reference.removeEventListener(this)
}
答案 0 :(得分:1)
如果您可以轻松使用Java8或某些Optional,则可以使用以下结构:
@Test
void name() {
TestScheduler scheduler = new TestScheduler();
Observable<Optional<Integer>> o1$ =
Observable.just(Optional.ofNullable(4)).mergeWith(Observable.never());
Observable<Optional<Integer>> o2$ =
Observable.just(Optional.ofNullable(2)).mergeWith(Observable.never());
Observable<Optional<Integer>> o3$ =
Observable.<Optional<Integer>>never()
.timeout(1000, TimeUnit.MILLISECONDS, scheduler)
.onErrorResumeNext(
throwable -> {
return Observable.<Optional<Integer>>never()
.mergeWith(Observable.just(Optional.empty()));
});
Observable<Tuple3<Optional<Integer>, Optional<Integer>, Optional<Integer>>> result =
Observable.combineLatest(
o1$,
o2$,
o3$,
(integer, integer2, integer3) -> Tuple.of(integer, integer2, integer3))
.filter(t -> t._1.isPresent() && t._2.isPresent() && t._3.isPresent());
TestObserver<Tuple3<Optional<Integer>, Optional<Integer>, Optional<Integer>>> test =
result.test();
scheduler.advanceTimeTo(10000, TimeUnit.SECONDS);
test.assertNotComplete().assertNoErrors().assertNoValues();
}
您可能没有,不允许通过observables-pipeline发出null值。因此,我们需要其他一些构造来表示null。在Java8中,有一个名为Optional的结构(vavr称其为Option-> Java8)。
在此示例中,o3 $ -Observable将不会发出任何东西。也可能会出错,也许这与您的情况有点相似。我们将捕获错误(在这种情况下为timeout-exception),并返回带有Optional.empty的Observable。
在组合回调中,我们组合所有三个值。在随后的步骤中,我们将筛选出所有具有有效值(带值的可选值)的元组。
只有在所有三个值都发出一个值后,您才会发出一个值。
当您不能使用Optional-class时,也可以像下面的示例一样定义INVALID-Object:
class So51217041 {
private static Integer INVALID_VALUE = 42;
@Test
void name() {
Observable<Integer> o1$ = Observable.just(4).mergeWith(Observable.never());
Observable<Integer> o2$ = Observable.just(2).mergeWith(Observable.never());
Observable<Integer> o3$ =
Observable.<Integer>never()
.onErrorResumeNext(
throwable -> {
return Observable.<Integer>never().mergeWith(Observable.just(INVALID_VALUE));
});
Observable<Tuple3<Integer, Integer, Integer>> result =
Observable.combineLatest(
o1$,
o2$,
o3$,
(integer, integer2, integer3) -> Tuple.of(integer, integer2, integer3))
.filter(t -> t._3 != INVALID_VALUE); // yeah I know, I want to compare reference, not the content
TestObserver<Tuple3<Integer, Integer, Integer>> test = result.test();
test.assertNotComplete().assertNoErrors().assertNoValues();
}
}
此外,当您希望流以INVALID或NULL开头时,CombineLatest发出至少一个值,则可以使用Observable#startWith(INVALID)或Observable#startWith(Optional.empty())。这将确保可观察对象至少发出一个值。
答案 1 :(得分:1)
您可以使用public final Single first(T defaultItem)方法。所以代码看起来像这样
getLatestLog.execute()
.first(someDefaultNonNullLog)
.toObservable()