2017-07-26 32 views
5

Jestem bardzo podekscytowany nowym RxJava Sources takich jak: Single, Maybe, Completable, które sprawiają, że interfejsy klasy czystsze i zapobiec wielu błędów podczas tworzenia waszych „Źródło” (np. zapominając zadzwonić pod numer onComplete())rxJava2 Łącząc pojedyncze, Może Completable w złożonych strumieni

Ale wymaga to wielu elementów, aby połączyć je w złożony strumień.

E.g. mamy typową sytuację Androida ładowania i buforowania danych. Załóżmy, że mamy 2 źródła api i cache i chcielibyśmy go łączyć:

public interface Api { 
    Single<Integer> loadFromNetwork(); 
} 

public interface Cache { 
    Maybe<Integer> loadFromCache(); //maybe because cache might not have item. 
} 

spróbujmy połączyć go:

final Single<Integer> result = cache.loadFromCache() 
     .switchIfEmpty(api.loadFromNetwork()); 

nie będzie kompilować, ponieważ Maybe nie ma przeciążenia Maybe.switchIfEmpty(Single):Single

więc musimy konwertować wszystko:

final Single<Integer> result = cache.loadFromCache() 
     .switchIfEmpty(api.loadFromNetwork().toMaybe()) 
     .toSingle(); 

Innym możliwym sposobem, aby połączyć je również wymaga сonversion:

final Single<Integer> result = Observable.concat(
      cache.loadFromCache().toObservable(), 
      api.loadFromNetwork().toObservable() 
     ).firstOrError(); 

Więc ja nie widzę żadnego sposobu korzystania z nowych źródeł bez wielu przemian, które dodają hałasu kodu i stworzyć wiele dodatkowych przedmiotów.

Z powodu takich problemów nie mogę używać Single, Maybe, Completable i nadal używać wszędzie Observable.

Więc moje pytanie brzmi:

  • Jakie są najlepsze praktyki łączenia Single, Maybe, Completable.

  • Dlaczego te źródła nie mają przeciążeń, aby ułatwić rozczesywanie.

  • Dlaczego te źródła nie mają wspólnego przodka i używają go jako parametru z parametru switchIfEmpty i innych metod?


PS: Czy ktoś wie, dlaczego te klasy nie mają wspólnej hierarchii?
Z mojej perspektywy, jeśli jakiś kod może działać na przykład z Completable, to również działa dobrze z Single i Maybe?

+0

Myślę, że [to] (https://stackoverflow.com/a/43890691/6774854) obejmuje wszystko oprócz najlepszych praktyk. Jeśli potrzebujesz metody, takiej jak 'switchIfEmptySingle', możesz poprosić o nią. – masp

+0

Kiedy element nie jest dostępny w pamięci podręcznej i ładujesz go z sieci, czy chcesz, aby połączenie sieciowe aktualizowało również dane w pamięci podręcznej? To, co mówię, to dlaczego chcesz połączyć te dwa? Załóżmy, że masz pamięć podręczną, na przykład bazę danych pokoju i obserwujesz tabelę z 'Płynnym', ten strumień nie będzie emitował, jeśli nie ma nic konkretnego dla twojego zapytania. W tym samym czasie wysyłasz żądanie i jeśli są zwrócone dane i kiedy umieścisz je w swoim stole, a jest inaczej, "Płynie" wyemituje. – arubin

Odpowiedz

0

Może i nie jest to kompleksowa odpowiedź, ale postaram się odpowiedzieć do konkretnego przypadku użycia:

myślę, że cel swojej łączącej zadaniem jest pobranie danych z pamięci podręcznej, jeśli wynik jest pusty chcesz zadzwonić zdalnego api:

final Single<List<Integer>> single = api.call(); 
    Maybe<List<Integer>> maybe = disk.call(); 


    Single <List<Integer>> composedSingle = maybe.flatMapSingle(new Function<List<Integer>, SingleSource<?>>() { 
     @Override 
     public SingleSource<?> apply(List<Integer> integers) throws Exception { 
      if(integers.isEmpty()) return single; 
      else return Single.just(integers); 
     } 
    }); 

Nie testowałem tego, ale myślę, że może być możliwe rozwiązanie (nie jestem pewien, czy najlepszy).

+1

, jeśli może po prostu kończy się bez emisji, 'flatMapSingle' rzuci wyjątek. – masp

+0

tak, masz rację. Więc powinienem usunąć proponowane rozwiązanie i odpowiedź w ogóle? – Fabio

+0

W proponowanym kodzie jest jeszcze jeden problem: pusta lista nie jest najlepszym sposobem wskazania, że ​​nie ma takiego elementu w pamięci podręcznej, ponieważ nie pozwala na cache poprawnie pustą odpowiedź z serwera. –