Rxjava doc definicja switchmap jest dość niejasne i linki do tej samej strony jak flatmap. Jaka jest różnica między tymi dwoma operatorami?
Rxjava doc definicja switchmap jest dość niejasne i linki do tej samej strony jak flatmap. Jaka jest różnica między tymi dwoma operatorami?
Odpowiedzi:
Zgodnie z dokumentacją ( http://reactivex.io/documentation/operators/flatmap.html )
switchMap
jest jak flatMap
, ale będzie emitować tylko przedmioty z nowej zaobserwować aż nowe zdarzenie jest emitowany od obserwowalnych źródłowego.
Diagram w marmurze dobrze to pokazuje. Zwróć uwagę na różnicę w diagramach:
W switchMap
drugiej oryginalnej emisji ( zielony marmur ) nie emituje drugiej zmapowanej emisji ( zielony kwadrat ), ponieważ trzecia pierwotna emisja ( niebieski marmur ) rozpoczęła się i już wyemitowała swoją pierwszą zmapowaną emisję ( niebieski diament ). Innymi słowy, ma miejsce tylko pierwsza z dwóch zmapowanych emisji zielonych; żaden zielony kwadrat nie jest emitowany, ponieważ niebieski diament go pokonał.
W programie flatMap
zostaną wyemitowane wszystkie zmapowane wyniki, nawet jeśli są „nieaktualne”. Innymi słowy, zdarzają się zarówno pierwsza , jak i druga zmapowana zielona emisja - wyemitowany zostałby zielony kwadrat (gdyby używali spójnej funkcji mapy; ponieważ tego nie zrobili, zobaczysz drugi zielony diament, mimo że jest emitowany po pierwszy niebieski diament)
flatMap
.map(func).switch
, ale to to samo co .switchMap(func)
.
Natknąłem się na to podczas implementacji „wyszukiwania błyskawicznego” - tj. Gdy użytkownik wpisuje w polu tekstowym, a wyniki pojawiają się niemal w czasie rzeczywistym po każdym naciśnięciu klawisza. Wydaje się, że rozwiązaniem jest:
W przypadku flatMap wyniki wyszukiwania mogą być nieaktualne, ponieważ odpowiedzi wyszukiwania mogą nie być w kolejności. Aby to naprawić, należy użyć switchMap, ponieważ zapewnia to anulowanie subskrypcji starego obserwowalnego po dostarczeniu nowszego.
Podsumowując, flatMap powinien być używany, gdy wszystkie wyniki mają znaczenie, niezależnie od ich czasu, a switchMap powinien być używany, gdy wyniki pochodzą tylko z ostatniej obserwowalnej materii.
Nie flatMap dyskusja jest kompletna bez porównywania i kontrastujący z switchMap
, concatMap
i concatMapEager
.
Wszystkie te metody wymagają Func1
przekształcenia strumienia w Observable
s, które są następnie emitowane; Różnica polega na tym, że zwracane Observable
s są subskrybowane i anulowane oraz czy i kiedy te emisje tych Observable
s są emitowane przez danego ____Map
operatora.
flatMap
subskrybuje jak najwięcej wyemitowanych Observable
s. (Jest to numer zależny od platformy. Np. Niższa liczba na Androidzie) Użyj tego, gdy zamówienie NIE jest ważne i chcesz, aby emisje były jak najszybciej.concatMap
subskrybuje pierwszy Observable
i subskrybuje następny Observable
dopiero po zakończeniu poprzedniego. Użyj tego, gdy porządek jest ważny i chcesz oszczędzać zasoby. Doskonałym przykładem jest odroczenie połączenia sieciowego przez sprawdzenie pamięci podręcznej w pierwszej kolejności. Zwykle może to nastąpić po znaku .first()
lub, .takeFirst()
aby uniknąć wykonywania niepotrzebnej pracy.
http://blog.danlew.net/2015/06/22/loading-data-from-multiple-sources-with-rxjava/
concatMapEager
działa podobnie, ale subskrybuje jak najwięcej (zależnie od platformy), ale będzie emitować dopiero po zakończeniu poprzedniej Observable
. Idealne, gdy musisz wykonać dużo równoległego przetwarzania, ale (w przeciwieństwie do flatMap) chcesz zachować pierwotną kolejność.
switchMap
zasubskrybuje ostatni Observable
napotkany plik i anuluje subskrypcję wszystkich poprzednich Observable
. Jest to idealne rozwiązanie w przypadkach takich jak sugestie wyszukiwania: gdy użytkownik zmieni zapytanie wyszukiwania, stare żądanie nie jest już interesujące, więc jest anulowane, a dobrze działający punkt końcowy interfejsu API anuluje żądanie sieciowe.Jeśli zwracasz Observable
pliki, które nie są subscribeOn
innym wątkiem, wszystkie powyższe metody mogą zachowywać się podobnie. To ciekawe i użyteczne zachowanie pojawia się, gdy pozwalasz zagnieżdżonym Observable
s działać na ich własnych wątkach. Następnie można uzyskać uzyskać wiele korzyści z przetwarzania równoległego i inteligentnie wypisywania lub nie subskrybowania z Observable
S, które nie interesują się swoimi Subscriber
s
amb
może być również interesujące. Biorąc pod uwagę dowolną liczbę Observable
s, emituje te same elementy, które Observable
emituje pierwszy, który cokolwiek wyemitował. Może to być przydatne, gdy masz wiele źródeł, które mogą / powinny zwracać to samo i chcesz wydajności. np. sortowanie, możesz amb
posortować szybko przez scalanie i użyć tego, co było szybsze.If you are returning Observables that don't subscribeOn another thread, all of the above methods may behave much the same.
- każde wyjaśnienie, z switchMap vs flatMap
jakim się spotkałem wcześniej, pomijało ten ważny aspekt, teraz wszystko jest jaśniejsze. Dziękuję Ci.
switchMap był kiedyś nazywany flatMapLatest w RxJS 4.
Po prostu przekazuje wydarzenia z ostatniego Observable i anuluje subskrypcję z poprzedniego.
Map, FlatMap, ConcatMap i SwitchMap stosują funkcję lub modyfikują dane emitowane przez Observable.
Mapa modyfikuje każdy element emitowany przez źródło Observable i emituje zmodyfikowany element.
FlatMap, SwitchMap i ConcatMap również stosują funkcję do każdego emitowanego elementu, ale zamiast zwracać zmodyfikowany element, zwraca sam Observable, który może ponownie emitować dane.
Praca z FlatMap i ConcatMap jest prawie taka sama. Scalają elementy emitowane przez wiele Observables i zwracają jeden Observable.
Jeśli szukasz przykładowego kodu
/**
* We switch from original item to a new observable just using switchMap.
* It´s a way to replace the Observable instead just the item as map does
* Emitted:Person{name='Pablo', age=0, sex='no_sex'}
*/
@Test
public void testSwitchMap() {
Observable.just(new Person("Pablo", 34, "male"))
.switchMap(person -> Observable.just(new Person("Pablo", 0, "no_sex")))
.subscribe(System.out::println);
}
Możesz zobaczyć więcej przykładów tutaj https://github.com/politrons/reactive
switchMap
ze flatMap
to będzie działać dokładnie tak samo.
Oto jeszcze jeden przykład o długości 101 linii . To wszystko wyjaśnia.
Jak powiedziano: dostaje ostatnią obserwowalną (najwolniejszą, jeśli wolisz) i ignoruje resztę.
W rezultacie:
Time | scheduler | state
----------------------------
0 | main | Starting
84 | main | Created
103 | main | Subscribed
118 | Sched-C-0 | Going to emmit: A
119 | Sched-C-1 | Going to emmit: B
119 | Sched-C-0 | Sleep for 1 seconds for A
119 | Sched-C-1 | Sleep for 2 seconds for B
1123 | Sched-C-0 | Emitted (A) in 1000 milliseconds
2122 | Sched-C-1 | Emitted (B) in 2000 milliseconds
2128 | Sched-C-1 | Got B processed
2128 | Sched-C-1 | Completed
Widzisz, A zostało zignorowane.