2017-02-08 8 views
2

Я realtive новичок в RxJava, так что я изо всех сил делать такого рода вещи, вещьСоздание Наблюдаемые из списка в зависимости от условий

У меня есть один Observable, испускающий отображение списка из другого класса под названием Gatekeeper как это:

 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(), но это не кажется, правильный подход к реактивному X, так что я хотел бы знать, как сделать это правильно ,

+1

http://stackoverflow.com/a/38212879/2450152 Это именно то, что вы хотите сделать. Использовать фильтры и методы карты –

ответ

2

Так что ваша проблема в том, что функция проверки является в основном Наблюдаемые? Слишком плохой фильтр не может восприниматься как предикат. Вы можете выполнить плоскосплавную функцию проверки, но при этом вы теряете ссылку на объект, на который была проверена функция проверки. Однако вы могли бы использовать временный объект для хранения как объекта, так и результата функции проверки, а затем фильтрацию свойства результата.

Это идея того, что он мог бы посмотреть. Заметки Северала;

  • Во-первых, я переписал ваш код с помощью основных операторов, карты, карты и фильтра, чтобы упростить его.

  • Во-вторых, я использовал Observable для всего, но вы могли добиться более выразительных сигнатур функций, используя Single для isValidGate (...) и Maybe для ближайшегоValidGate (...).

  • Последнее, что я использовал Rx 2, но с Rx 1 он должен быть в основном тем же.

код в 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 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.

+0

Решил это с помощью этого решения, спасибо! Хотя пришлось получить дополнительную промежуточную планшетную таблицу, причина в том, что gatevalidation был более сложным в зависимости от связанной с ним парковки, но с этой базой я смог выполнить то, что хотел. – Kngihtkiller81

1

Прежде всего, ваш первый метод может быть написан гораздо succintly как:

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

Обратите внимание, что вы, вероятно, не нужен ToList(), если учесть все ваши Наблюдаемые быть итераторов-эквиваленты.

Чтобы отфильтровать ворота, которые не являются допустимыми, просто используйте filter оператор:

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

См? Все проще, если вы не смешиваете коллекции и Observables.

1

Я хочу создать Observable, который излучает только первый элемент, который действует

Чтобы испускают первый элемент, который соответствует с данным предикатом, в соответствии с вашими требованиями, вы можете использовать либо оператор first с предикатом first(Func1<? super T, Boolean> predicate) или firstOrDefault со значением по умолчанию и предикатом firstOrDefault(T defaultValue, Func1<? super T, Boolean> predicate).

В вашем случае это может быть что-то вроде этого:

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