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 )
switchMapjest 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 switchMapdrugiej 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 flatMapzostaną 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, concatMapi concatMapEager.
Wszystkie te metody wymagają Func1przekształcenia strumienia w Observables, które są następnie emitowane; Różnica polega na tym, że zwracane Observables są subskrybowane i anulowane oraz czy i kiedy te emisje tych Observables są emitowane przez danego ____Mapoperatora.
flatMapsubskrybuje jak najwięcej wyemitowanych Observables. (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.concatMapsubskrybuje pierwszy Observablei subskrybuje następny Observabledopiero 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/
concatMapEagerdział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ść.
switchMapzasubskrybuje ostatni Observablenapotkany 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 Observablepliki, które nie są subscribeOninnym wątkiem, wszystkie powyższe metody mogą zachowywać się podobnie. To ciekawe i użyteczne zachowanie pojawia się, gdy pozwalasz zagnieżdżonym Observables 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 ObservableS, które nie interesują się swoimi Subscribers
ambmoże być również interesujące. Biorąc pod uwagę dowolną liczbę Observables, emituje te same elementy, które Observableemituje 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 ambposortować 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 flatMapjakim 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
switchMapze flatMapto 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.