Jaka jest różnica między flatmap a switchmap w RxJava?

RxJava Doc definicja switchmap jest dość niejasna i łączy się z tą samą stroną Co flatmap. Jaka jest różnica między tymi dwoma operatorami?

Author: Julian Go, 2015-01-27

6 answers

Zgodnie z dokumentacją ( http://reactivex.io/documentation/operators/flatmap.html )

{[0] } jest jak flatMap, ale będzie emitować tylko elementy z nowego obserwowalnego dopóki nie zostanie wyemitowane nowe zdarzenie ze źródła obserwowalnego.

Marmurowy diagram dobrze to pokazuje. Zauważ różnicę w diagramach:

In switchMap The second originalemission ( green marble ) does not emit its second mapped emission (green square), od trzeciego original emission (blue marble) rozpoczął i już wyemitował swój pierwszy mapped emission (blue diamond). Innymi słowy, tylko pierwsza z dwóch zmapowanych Zielona emisja występuje; żaden zielony kwadrat nie jest emitowany, ponieważ niebieski diament go pokonał.

W flatMap Wszystkie zmapowane wyniki będą emitowane, nawet jeśli są "nieświeże". Innymi słowy, zarówno pierwszy jak i drugi z zmapowane zielone emisje się zdarzają -- zielony kwadrat zostałby wyemitowany (jeśli użyliby spójnej funkcji mapy; ponieważ nie, widzisz drugi zielony diament, mimo że jest emitowany po pierwszy niebieski diament)

SwitchMap w switchmapie jeśli oryginalny obserwowalny emituje coś nowego, poprzednie emisje nie wytwarzają już mapowanych obserwowalnych; jest to skuteczny sposób na uniknięcie starych wyników

FlatMap

w switchmapie jeśli oryginalny obserwowalny emituje coś nowego, poprzednie emisje nie wytwarzają już mapowanych obserwowalnych; jest to skuteczny sposób na uniknięcie starych wyników

 143
Author: dwursteisen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-19 01:46:01

Natknąłem się na to podczas implementacji "instant search" - tj. gdy użytkownik wpisuje tekst w polu tekstowym, a wyniki pojawiają się w czasie niemal rzeczywistym z każdym naciśnięciem klawisza. Rozwiązaniem wydaje się być:

  1. mieć temat, np. PublishSubject of String
  2. w polu tekstowym Zmień callback, wywołaj .onNext (text)
  3. Zastosuj .debounce filter to rate limit server queries
  4. Zastosuj .switchMap do wykonania zapytania serwera-przybierając wyszukiwaną frazę i zwracając SearchResponse
  5. Zastosuj .Subskrybuj za pomocą metody, która zużywa SearchResponse i aktualizuje interfejs użytkownika.

Z flatMap wyniki wyszukiwania mogą być nieświeże, ponieważ odpowiedzi wyszukiwania mogą wrócić nie w porządku. Aby to naprawić, należy użyć switchMap, ponieważ zapewnia, że stary obserwowalny jest anulowany 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 tylko wyniki z ostatniej Obserwowalnej materii.

 140
Author: user4698855,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-20 22:20:37

Żadna dyskusja flatMap nie jest kompletna bez porównywania i kontrastowania z switchMap, concatMap i concatMapEager.

Wszystkie te metody przyjmują Func1, które przekształcają strumień w Observables, które są następnie emitowane; różnica polega na tym, że zwrócone Observables są subskrybowane i anulowane, oraz jeśli i kiedy te emisje tych {4]} S są emitowane przez dany operator ____Map.

  • flatMap subskrybuje jak najwięcej emitowanych Observables. (Jest to platforma zależna numer. tzn. niższa liczba na Androida) Użyj tego, gdy zamówienie nie jest ważne, a chcesz jak najszybciej.
  • concatMap subskrybuje pierwszą Observable i subskrybuje następną Observable dopiero po zakończeniu poprzedniej. Użyj tego, gdy zamówienie jest ważne i chcesz oszczędzać zasoby. Doskonałym przykładem jest odroczenie połączenia sieciowego przez sprawdzenie najpierw pamięci podręcznej. Po którym zazwyczaj następuje .first() lub .takeFirst(), aby uniknąć niepotrzebnego praca.

    Http://blog.danlew.net/2015/06/22/loading-data-from-multiple-sources-with-rxjava/

  • concatMapEager działa tak samo, ale subskrybuje tak wiele, jak to możliwe (zależne od platformy), ale emituje tylko po zakończeniu poprzedniej Observable. Idealny, gdy masz dużo przetwarzania równoległego, które musi być wykonane, ale (w przeciwieństwie do flatMap) chcesz zachować pierwotną kolejność.

  • switchMap zapisze się do ostatniego Observable i Anuluj subskrypcję ze wszystkich poprzednich Observable s. jest to idealne rozwiązanie dla takich przypadków jak sugestie wyszukiwania: Gdy użytkownik zmieni swoje zapytanie wyszukiwania, stare żądanie nie jest już interesujące, więc jest anulowane, a dobrze zachowujący się punkt końcowy Api anuluje żądanie sieciowe.

Jeśli zwracasz Observable S, które nie zawierają subscribeOn innego wątku, wszystkie powyższe metody mogą zachowywać się tak samo. Ciekawe i użyteczne zachowanie pojawia się, gdy pozwalasz zagnieżdżonym Observable s działać samodzielnie nici. Dzięki temu możesz uzyskać wiele korzyści z przetwarzania równoległego i inteligentnie zrezygnować z subskrypcji lub nie subskrybować z Observables, które nie interesują twojego Subscribers

  • amb mogą być również interesujące. Biorąc pod uwagę dowolną liczbę Observables emituje te same elementy, które emituje pierwsza Observable, która emituje cokolwiek. To może być przydatne, gdy masz wiele źródeł, które mogą/powinny zwrócić to samo i chcesz wydajności. na przykład sortowanie, możesz amb sortować szybko z sortowaniem merge-sort i użyj tego, co było szybsze.
 73
Author: Andrew Gallasch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-18 05:39:43

SwitchMap był kiedyś nazywany flatMapLatest w RxJS 4.

Po prostu przekazuje wydarzenia z ostatniego obserwowalnego i wypisuje się z poprzedniego.

 48
Author: Sentenza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-02 19:01:36

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

 0
Author: paul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-19 17:16:50

Oto jeszcze jeden-101 linijek długości przykład . To wszystko wyjaśnia.

Jak zostało powiedziane: dostaje ostatnią obserwowalną (najwolniejszą, jeśli chcesz) i ignoruje resztę.

W wyniku:

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, że A zostało zignorowane.

 0
Author: ses,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-22 17:35:22