[英]RxJava- CombineLatest but only fire for one Observable's emission?
[英]RxJava: how to handle combineLatest() when one of the streams emits nothing
我使用combineLatest()來組合3個可觀察流。 所有這些組合在一起,以便UI中的所有數據同時顯示。 現在,有一種情況是其中一個observable不會發出任何內容,因為獲取的數據可以為null。
是否有一個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()
}
第三個流:getLatestLog.execute()在用戶具有nog日志時不發出任何內容。 當此流未發出時,整個視圖將不可見。
數據從FireBase實時數據庫中獲取。 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)
}
如果你手上有Java8或一些Optionals,你可以使用這個結構:
@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。 在Java8中有一個名為Optional的構造(vavr稱之為Option - >也是Java8)。
在這個例子中,o3 $ -Observable不會發出任何東西。 它也可能是錯誤的,也許這類似於你的情況。 我們將捕獲錯誤(在這種情況下:timeout-exception)並返回帶有Optional.empty的Observable。
在組合回調中,我們將三個值組合起來。 在后面的步驟中,我們過濾掉所有元組,它們都具有有效值(Optional with Value)。
只有在使用值發出所有三個值時,才會獲得一個值。
如果不能使用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())。 這將保證,observable至少會發出一個值。
您可以使用public final Single first(T defaultItem)方法。 所以代碼可能看起來像這樣
getLatestLog.execute()
.first(someDefaultNonNullLog)
.toObservable()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.