首页 文章

根据条件从列表中创建Observable

提问于
浏览
2

我是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)

我看到的一个简单方法是使用 toBlocking.first()Observable<ParkappParking>Observable<Boolean> 转换为值,但这似乎不是Reactive X的正确方法,因此我想知道如何正确执行 .

3 回答

  • 1

    所以你的问题是你的验证函数基本上是一个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

    首先,你的第一种方法可以更加简洁地写成:

    Observable
      .from(gates)
      .flatMap(gate -> mDataManager.getGateById(gate.getCode()))
    

    请注意,如果您将所有Observable视为等效迭代器,则可能不需要toList() .

    要过滤掉无效的门,只需使用 filter 运算符:

    .filter(gate -> isValidGate(gate))
      .first()
    

    看到?如果不混合集合和Observable,一切都会更容易 .

  • 2

    我想创建一个Observable,它只发出第一个有效的项目

    要根据您的要求发出与给定谓词匹配的第一个项目,您可以使用带有谓词first(Func1<? super T, Boolean> predicate)的运算符 first 或带有默认值的 firstOrDefault 和谓词firstOrDefault(T defaultValue, Func1<? super T, Boolean> predicate) .

    在你的情况下,它可能是这样的:

    ...
    .first(this::isValidGate);
    

相关问题