Вызовите службу, только если предыдущая наблюдаемая успешна

Фон

Я просто погружаюсь в концепцию RX для java. Честно говоря, я не понимаю. В моем проекте я использую модифицированную библиотеку для вызова сервисов. В настоящее время я реализовал все сервисы с помощью обратного вызова. Если я хочу организовать сервисные вызовы, я должен вызывать обратные вызовы в обратных вызовах, что приводит к довольно запутанному коду.

Проблема

Для следующих двух служб я хотел бы вызвать службу B, если служба A успешно завершена с использованием подхода Observables.

public interface RetrofitRestService {

    @GET("...")
    Observable<Object> A();

    @GET("...")
    Observable<Object> B();
}

Я искал наблюдаемые операторы , которые мог бы использовать для своей задачи, но безуспешно. Я могу представить себе такого оператора:

RetrofitRestServices service;
service.A().ifSuccessfull(B());

//OR
service.A().ifWasNotEmpty(B());

//OR
service.A().useCondition(new Condition(){ ... }, B());

person Amio.io    schedule 23.02.2015    source источник


Ответы (2)


Если вы хотите позвонить А, то позвоните Б, вы можете использовать оператор concat : Б будет вызван, если А завершится.

service.A().concatWith(service.B()).subscribe();

Но если A вернет null, будет вызван B.

Если это так, то этот ответ будет лучше: https://stackoverflow.com/a/28685808/476690

ИЗМЕНИТЬ после комментария

Если вы хотите использовать результат A(), вам нужен оператор flatMap.

service.A().flatMap(resultOfA -> service.B(resultOfA)).subscribe();

(предоставление resultOfA в качестве аргумента B() является просто примером использования)

Другой способ:

Вы также можете построить результат из ответа A и ответа B

service.A().flatMap(resultOfA -> service.B().zipWith(Observable.just(resultOfA), (a, b) -> new ResultOf(a, b))).subscribe();

В этом случае zipoperator создаст результат с результатом A и B. ResultOf — это просто пример класса, показывающий, как построить результат с результатом A и B.

Дополнительная информация о flapMap: Когда вы используете карту против flatMap в RxJava?

person dwursteisen    schedule 24.02.2015
comment
Я собираюсь попробовать это сегодня днем. Как я могу работать с результатом A(), а затем использовать concatWith? Мне нужно обработать результат A(). Если это более длинное решение, добавьте редактирование в свой ответ. - person Amio.io; 24.02.2015
comment
Новая информация выглядит великолепно. Я до сих пор не добрался до дома. Но не могу дождаться, чтобы проверить это. Я верю, что это сработает. Еще одна вещь... В Android мы все еще используем Java 6, никаких замыканий. Как бы вы записали service.A().flatMap(resultOfA -> service.B(resultOfA)).subscribe(); в Java 6. Я имею в виду, в частности, resultOfA -> ... . - person Amio.io; 24.02.2015
comment
Вы не можете, из коробки. Но вы можете попробовать retrolambda (плагин gradle: github.com/evant/gradle-retrolambda). Он преобразует лямбда в анонимный класс. Я использовал его в небольшом проекте Android. Но у некоторых людей есть некоторые проблемы с этим (я полагаю, с прогуадом) - person dwursteisen; 24.02.2015
comment
Спасибо за вашу помощь. Это было так! - person Amio.io; 25.02.2015

Как насчет этого:

service.A().isEmpty().filter(new Func1<Boolean, Boolean>() {
    @Override
    public Boolean call(Boolean empty) {
        return !empty;
    }
})
.flatMap(new Func1<Boolean, Observable<? extends Object>>() {
    @Override
    public Observable<? extends Integer> call(Boolean empty) {
        return B();
    }
});

Оператор isEmpty выдает логическое значение, которое будет истинным только в том случае, если A() ничего не выдает. Вот почему, если A() выдает элемент, фильтр, проверяющий, пройдет ли результат isEmpty, и будет вызван flatMap, тем самым вызывая B().

person meddle    schedule 23.02.2015
comment
Я собираюсь попробовать это сегодня днем. Как я могу работать с результатом A(), а затем использовать flatMap? Мне нужно обработать результат A(). Если это более длинное решение, добавьте редактирование в свой ответ. - person Amio.io; 24.02.2015
comment
Хм, если вам нужен фактический результат A(), вы можете либо кэшировать его, а затем использовать приведенную выше логику для запуска B(), либо, если B использует результат A(), используйте ответ, предоставленный dwursteisen. Похоже, вам нужно что-то похожее на предоставленный им код, поэтому я ставлю +1 к его ответу. - person meddle; 25.02.2015
comment
Thx Meddle, ваш ответ помог мне лучше понять наблюдаемые. - person Amio.io; 25.02.2015