Как связать два завершенных в RxJava2

У меня два Завершенных. Я хотел бы сделать следующий сценарий: Если первый Заполненный получает onComplete, продолжайте второй Завершенный. Конечные результаты будут onComplete второго Completed.

Вот как я это делаю, когда у меня есть Single getUserIdAlreadySavedInDevice() и Completed login():

@Override
public Completable loginUserThatIsAlreadySavedInDevice(String password) {
    return getUserIdAlreadySavedInDevice()
            .flatMapCompletable(s -> login(password, s))

}

Ответ 1

Вы ищете оператора andThen.

Возвращает Завершающий, который сначала запускает этот Завершенный, а затем другой завершаемый.

firstCompletable
    .andThen(secondCompletable)

В общем случае этот оператор является "заменой" для a flatMap на Completable:

Completable       andThen(CompletableSource next)
<T> Maybe<T>      andThen(MaybeSource<T> next)
<T> Observable<T> andThen(ObservableSource<T> next)
<T> Flowable<T>   andThen(Publisher<T> next)
<T> Single<T>     andThen(SingleSource<T> next)

Ответ 2

TL; DR: другие ответы пропускают тонкость. Используйте doThingA().andThen(doThingB()), если вы хотите эквивалент concat, используйте doThingA().andThen(Completable.defer(() -> doThingB()), если вы хотите эквивалент flatMap.

Приведенные выше ответы являются своего рода правильными, но я нашел их вводящими в заблуждение, потому что они упускают тонкость в отношении нетерпеливой оценки.

doThingA().andThen(doThingB()) немедленно вызовет doThingB(), но подписывается только на наблюдаемую информацию, возвращаемую doThingB(), когда завершается наблюдаемая, возвращаемая doThingA().

doThingA().andThen(Completable.defer(() -> doThingB()) позвонит doThingB() только после того, как вещь А будет завершена.

Это важно только в том случае, если doThingB() имеет побочные эффекты перед событием подписки. Например. Single.just(sideEffect(1)).toCompletable()

Реализация, у которой нет побочных эффектов перед событием подписки (наблюдаемая в холодном состоянии), может быть Single.just(1).doOnSuccess(i -> sideEffect(i)).toCompletable().

В случае, который только что укусил меня, A - это некоторая логика проверки, и doThingB() немедленно запускает асинхронное обновление базы данных, которое завершает VertX ObservableFuture. Это плохо. Возможно doThingB() должен быть написан, чтобы обновлять базу данных только после подписки, и я собираюсь попытаться спроектировать вещи таким образом в будущем.