我是RxJava的新手,所以我在努力做这类事情,事情是
我有一个Observable从另一个名为Gatekeeper的类发出List映射,如下所示:
List<ParkappGate> actualgates = Observable.just(gates).concatMap(new Func1<List<Gatekeeper>, Observable<? extends List<ParkappGate>>>() {
@Override
public Observable<? extends List<ParkappGate>> call(List<Gatekeeper> gatekeepers) {
final List<ParkappGate> gates = new ArrayList<ParkappGate>();
for (Gatekeeper gate :
gatekeepers) {
mDataManager.getGateById(gate.getCode()).subscribe(new Subscriber<ParkappGate>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(ParkappGate gate) {
gates.add(gate);
}
});
}
return Observable.just(gates);
}
});
这个工作正常,所以现在我想创建一个Observable,它只发出一些条件下列表中有效的第一个项目,我在这里创建的是这样的:
Observable<ParkappGate> nearestValidGate = actualgates.
concatMap(new Func1<List<ParkappGate>, Observable<? extends ParkappGate>>() {
@Override
public Observable<? extends ParkappGate> call(List<ParkappGate> parkappGates) {
for (ParkappGate gate :
parkappGates) {
if (isValidGate(gate))
return Observable.just(gate);
}
return null;
}
}
我的问题在于,在验证ParkappGate时,我必须调用我创建的一个返回Observable<ParkappParking>
的方法,另一个返回一个Observable并使用ParkappGate作为参数进行评估,然后返回如果方法isValidGate(ParkappGate gate)
我看到的一个简单方法是使用Observable<ParkappParking>
将Observable<Boolean>
和toBlocking.first()
转换为值,但这似乎不是Reactive X的正确方法,所以我想知道怎么做得对。
答案 0 :(得分:2)
所以你的问题是你的验证函数基本上是一个Observable?太糟糕的过滤器不能接受observable作为谓词。您可以对验证函数进行平面映射,但这样做会丢失对评估验证函数的对象的引用。但是,您可以使用临时对象来存储对象和验证函数的结果,然后对结果属性进行过滤。
这是它的外观。几个人注意到了;
首先,我用基础操作符map,flatmap和filter重写了你的代码以简化它。
其次,我使用了Observable,但你可以通过使用Single for isValidGate(...)和Maybe for nearestValidGate(...)来获得更具表现力的函数签名。
最后,我使用了Rx 2但是使用Rx 1它应该主要是相同的。
Java pre-8中的代码:
package io.nemo.commons;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;
import static java.lang.Boolean.TRUE;
public class ParkSO {
class Gatekeeper {
public int getCode() {
return 1; // Dump implementation
}
}
class ParkappGate {
}
class ParkappParking {
}
class DataManager {
public Observable<ParkappGate> getGateById(int code) {
return Observable.just(new ParkappGate()); // Dumb implementation
}
}
class GateKeeperValidation {
private ParkappGate gate;
private Boolean validation;
public ParkappGate getGate() {
return gate;
}
public Boolean getValidation() {
return validation;
}
public GateKeeperValidation(ParkappGate gate, Boolean validation) {
this.gate = gate;
this.validation = validation;
}
}
Observable<ParkappParking> getParking(ParkappGate gate) {
return Observable.just(new ParkappParking()); // Dumb implementation
}
Observable<Boolean> isValidParking(ParkappParking parking) {
return Observable.just(TRUE); // Dumb implementation
}
Observable<Boolean> isValidGate(ParkappGate gate) {
return getParking(gate)
.flatMap(new Function<ParkappParking, ObservableSource<Boolean>>() {
@Override
public ObservableSource<Boolean> apply(ParkappParking parkappParking) throws Exception {
return isValidParking(parkappParking);
}
});
}
void main() {
final DataManager mDataManager = new DataManager();
final List<Gatekeeper> gateKeepers = new ArrayList<>();
Observable.fromIterable(gateKeepers)
.flatMap(new Function<Gatekeeper, ObservableSource<ParkappGate>>() {
@Override
public ObservableSource<ParkappGate> apply(Gatekeeper gatekeeper) throws Exception {
return mDataManager.getGateById(gatekeeper.getCode());
}
})
.flatMap(new Function<ParkappGate, ObservableSource<GateKeeperValidation>>() {
@Override
public ObservableSource<GateKeeperValidation> apply(final ParkappGate parkappGate) throws Exception {
return isValidGate(parkappGate)
.map(new Function<Boolean, GateKeeperValidation>() {
@Override
public GateKeeperValidation apply(Boolean validation) throws Exception {
return new GateKeeperValidation(parkappGate, validation);
}
});
}
})
.filter(new Predicate<GateKeeperValidation>() {
@Override
public boolean test(GateKeeperValidation gateKeeperValidation) throws Exception {
return gateKeeperValidation.getValidation();
}
})
.firstElement();
}
}
使用Java 8的版本:
package io.nemo.commons;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;
import static java.lang.Boolean.TRUE;
public class ParkSOJava8 {
class Gatekeeper {
public int getCode() {
return 1; // Dump implementation
}
}
class ParkappGate {
}
class ParkappParking {
}
class DataManager {
public Observable<ParkappGate> getGateById(int code) {
return Observable.just(new ParkappGate()); // Dumb implementation
}
}
class GateKeeperValidation {
private ParkappGate gate;
private Boolean validation;
public ParkappGate getGate() {
return gate;
}
public Boolean getValidation() {
return validation;
}
public GateKeeperValidation(ParkappGate gate, Boolean validation) {
this.gate = gate;
this.validation = validation;
}
}
Observable<ParkappParking> getParking(ParkappGate gate) {
return Observable.just(new ParkappParking()); // Dumb implementation
}
Observable<Boolean> isValidParking(ParkappParking parking) {
return Observable.just(TRUE); // Dumb implementation
}
Observable<GateKeeperValidation> isValidGate(ParkappGate gate) {
return getParking(gate)
.flatMap(this::isValidParking)
.map(validation -> new GateKeeperValidation(gate, validation));
}
void main() {
final DataManager mDataManager = new DataManager();
final List<Gatekeeper> gateKeepers = new ArrayList<>();
Observable.fromIterable(gateKeepers)
.map(Gatekeeper::getCode)
.flatMap(mDataManager::getGateById)
.flatMap(this::isValidGate)
.filter(GateKeeperValidation::getValidation)
.firstElement();
}
}
您也可以编写自己的filterWithObservable或filterWithSingle运算符。
答案 1 :(得分:1)
首先,你的第一种方法可以更加简洁地写成:
filter
请注意,如果您认为所有Observable都是等效迭代器,则可能不需要toList()。
要过滤掉无效的大门,只需使用 .filter(gate -> isValidGate(gate))
.first()
运算符:
{{1}}
请参阅?如果你不混合集合和Observables,一切都会更容易。
答案 2 :(得分:1)
我想创建一个仅发出第一个项目的Observable 有效
要根据您的要求发出与给定谓词匹配的第一个项目,您可以使用带有谓词{{3}}或first
的运算符firstOrDefault
和默认值谓词first(Func1<? super T, Boolean> predicate)
。
在你的情况下,它可能是这样的:
...
.first(this::isValidGate);