我需要有关如何使用RxJava完成以下操作的建议。 我需要进行一系列链式调用,如果任何调用具有包含特定值的响应,则后续调用不得发生,并且必须返回该调用的值。
我正在尝试这样的事情:
public Observable<ReturnObject> doChainedApiCall() {
Observable<ReturnObject> obs = service.apiCall1()
.flatMap({
if (call1Response.hasValue) {
// don't do anymore api calls, return this
ReturnObject obj = new ReturnObject();
obj.setSomething();
return Observable.just(obj);
}
return service.apiCall2();
})
.flatMap({
if (call2Response.hasValue) {
// don't do anymore api calls, return this
ReturnObject obj = new ReturnObject();
obj.setSomething();
return Observable.just(obj);
}
return service.apiCall3();
})
.flatMap({
ReturnObject obj = new ReturnObject();
return Observable.just(obj);
});
return obs;
}
这段代码不会编译,只是对我想做的事情有所了解。
如何确保链在第一次调用时结束并在其中的检查为真时返回值?
答案 0 :(得分:2)
我找到了自己问题的答案。
Observable<ReturnObject> observable = Observable.concat(
apiCall1(),
apiCall2(),
apiCall3()
).flatMap(response -> {
if (response.value == whatWeAreLookingFor) {
ReturnObject obj = new ReturnObject();
// set obj properties and return it.
return Observable.just(obj);
}
// Return empty to continue with next call from .concat() list.
return null; // or return Observable.empty();
}).first(); // Makes sure only the first non-empty result is called and returned.
.first()
甚至可以替换为.firstOrDefault(Something)
,以确保最终返回的内容,如果3个api调用都没有我们正在寻找的内容。
感谢其他建议。我认为这种方式最简单,如果你知道一种更简单的方法,我很想知道。
答案 1 :(得分:1)
交换机是正确的轨道,但您必须编写自己的自定义运算符,如果条件满足则会切换,因为没有现有的条件。我从rxjava github存储库修改了OperatorSwitchIfEmpty
运算符来执行此操作
import rx.*;
import rx.functions.Func1;
import rx.internal.producers.ProducerArbiter;
import rx.subscriptions.SerialSubscription;
public final class OperatorSwitchIfMatch<T> implements Observable.Operator<T, T> {
private final Observable<? extends T> alternate;
private final Func1<T, Boolean> selector ;
public OperatorSwitchIfMatch(Observable<? extends T> alternate, Func1<T, Boolean> selector) {
this.alternate = alternate;
this.selector = selector;
}
@Override
public Subscriber<? super T> call(Subscriber<? super T> child) {
final SerialSubscription ssub = new SerialSubscription();
ProducerArbiter arbiter = new ProducerArbiter();
final ParentSubscriber<T> parent = new ParentSubscriber<T>(child, ssub, arbiter, alternate,selector);
ssub.set(parent);
child.add(ssub);
child.setProducer(arbiter);
return parent;
}
private static final class ParentSubscriber<T> extends Subscriber<T> {
private boolean matched = true;
private final Subscriber<? super T> child;
private final SerialSubscription ssub;
private final ProducerArbiter arbiter;
private final Observable<? extends T> alternate;
private final Func1<T, Boolean> selector ;
ParentSubscriber(Subscriber<? super T> child, final SerialSubscription ssub, ProducerArbiter arbiter, Observable<? extends T> alternate, Func1<T, Boolean> selector) {
this.child = child;
this.ssub = ssub;
this.arbiter = arbiter;
this.alternate = alternate;
this.selector = selector;
}
@Override
public void setProducer(final Producer producer) {
arbiter.setProducer(producer);
}
@Override
public void onCompleted() {
child.onCompleted();
}
private void subscribeToAlternate() {
AlternateSubscriber<T> as = new AlternateSubscriber<T>(child, arbiter);
ssub.set(as);
alternate.unsafeSubscribe(as);
}
@Override
public void onError(Throwable e) {
child.onError(e);
}
@Override
public void onNext(T t) {
if (selector.call(t)) {
if (!child.isUnsubscribed()) {
subscribeToAlternate();
}
} else {
child.onNext(t);
}
arbiter.produced(1);
}
}
private static final class AlternateSubscriber<T> extends Subscriber<T> {
private final ProducerArbiter arbiter;
private final Subscriber<? super T> child;
AlternateSubscriber(Subscriber<? super T> child, ProducerArbiter arbiter) {
this.child = child;
this.arbiter = arbiter;
}
@Override
public void setProducer(final Producer producer) {
arbiter.setProducer(producer);
}
@Override
public void onCompleted() {
child.onCompleted();
}
@Override
public void onError(Throwable e) {
child.onError(e);
}
@Override
public void onNext(T t) {
child.onNext(t);
arbiter.produced(1);
}
}
}
然后您可以像
一样使用它import rx.Observable;
public class SwitchMatchTest {
public static void main(String[] args) throws InterruptedException {
Observable<Integer> stream1 = Observable.just(9,1,1,1,1,9,1); // Will be skipped because it starts with 9
Observable<Integer> stream2 = Observable.just(9,2,2,2,9,11); // Will be skipped because stream2 starts with 9
Observable<Integer> stream3 = Observable.just(9,3,3,9,11);
Observable<Integer> stest = stream1.lift(new OperatorSwitchIfMatch<Integer>(stream2, x -> x>6)).lift(new OperatorSwitchIfMatch<Integer>(stream3, x -> x>6));
stest.subscribe(l -> System.out.println("Emitted : " + l), e -> {}, () -> System.out.println("Completed"));
Thread.sleep(2000L);
}
}
在你的情况下,你会使用像
这样的东西service.apiCall1().lift(new OperatorSwitchIfMatch<Response<AnObject>>(service.apiCall2(), x -> !x.hasValue))
.lift(new OperatorSwitchIfMatch<Response<AnObject>>(service.apiCall3(), x -> !x.hasValue))
.lift(new OperatorSwitchIfMatch<Response<AnObject>>(somedefaultObservable, x -> !x.hasValue))
答案 2 :(得分:0)
假设您的apiCallX
方法都返回Observable
,如果它们都在onCompleted
事件中正确完成,您可以使用switchIfEmpty
和/或{{1}运营商。像这样:
defaultIfEmpty
顺便说一下。 javadoc中列出了所有运算符(大多数包括大理石图)。