Die rxjava-Dokumentdefinition von switchmap ist ziemlich vage und verweist auf dieselbe Seite wie flatmap. Was ist der Unterschied zwischen den beiden Operatoren?
Die rxjava-Dokumentdefinition von switchmap ist ziemlich vage und verweist auf dieselbe Seite wie flatmap. Was ist der Unterschied zwischen den beiden Operatoren?
Antworten:
Laut Dokumentation ( http://reactivex.io/documentation/operators/flatmap.html )
Das switchMap
ist wie das flatMap
, aber es werden nur Elemente von der neuen Observable ausgegeben, bis ein neues Ereignis von der Source Observable ausgegeben wird.
Das Marmordiagramm zeigt es gut. Beachten Sie den Unterschied in den Diagrammen:
Bei switchMap
der zweiten ursprünglichen Emission ( grüner Marmor ) wird die zweite abgebildete Emission ( grünes Quadrat ) nicht emittiert , da die dritte ursprüngliche Emission ( blauer Marmor ) begonnen hat und bereits die erste abgebildete Emission ( blauer Diamant ) emittiert . Mit anderen Worten, nur die erste von zwei kartierten grünen Emissionen tritt auf; Es wird kein grünes Quadrat ausgegeben, weil der blaue Diamant es geschlagen hat.
In flatMap
werden alle zugeordneten Ergebnisse ausgegeben, auch wenn sie "veraltet" sind. Mit anderen Worten, sowohl ersten und zweiter der abgebildeten passieren grün - Emissionen - ein grünes Quadrat emittiert habe würde (wenn sie konsistent Map - Funktion verwendet, da sie nicht, haben Sie den sehen zweiten grünen Diamanten, auch wenn es ausgestrahlt wird nach der erste blaue Diamant)
flatMap
.map(func).switch
, aber das ist das gleiche wie .switchMap(func)
.
Dies ist mir bei der Implementierung der "Sofort-Suche" begegnet, dh wenn der Benutzer ein Textfeld eingibt und die Ergebnisse bei jedem Tastendruck nahezu in Echtzeit angezeigt werden. Die Lösung scheint zu sein:
Mit flatMap können die Suchergebnisse veraltet sein, da die Suchantworten möglicherweise nicht mehr in der richtigen Reihenfolge angezeigt werden. Um dies zu beheben, sollte switchMap verwendet werden, da dadurch sichergestellt wird, dass ein altes Observable abgemeldet wird, sobald ein neueres bereitgestellt wird.
Zusammenfassend sollte flatMap verwendet werden, wenn alle Ergebnisse unabhängig von ihrem Zeitpunkt von Bedeutung sind, und switchMap sollte verwendet werden, wenn nur Ergebnisse aus der letzten beobachtbaren Angelegenheit von Bedeutung sind.
Kein flatMap Diskussion ist ohne Vergleich und Kontrast mit switchMap
, concatMap
und concatMapEager
.
Alle diese Methoden nehmen eine Func1
, die den Strom in Observable
s umwandelt, die dann ausgegeben werden; Der Unterschied besteht darin, wann die zurückgegebenen Observable
s gezeichnet und nicht abonniert werden und ob und wann diese die Emissionen dieser Observable
s vom ____Map
betreffenden Betreiber emittiert werden .
flatMap
abonniert so viele emittierte Observable
s wie möglich. (Dies ist eine plattformabhängige Nummer, z. B. eine niedrigere Nummer unter Android.) Verwenden Sie diese Option, wenn die Reihenfolge NICHT wichtig ist und Sie so schnell wie möglich Emissionen wünschen.concatMap
Abonniert den ersten Observable
und erst den nächsten, Observable
wenn der vorherige abgeschlossen ist. Verwenden Sie diese Option, wenn die Reihenfolge wichtig ist und Sie Ressourcen schonen möchten. Ein perfektes Beispiel ist das Verschieben eines Netzwerkaufrufs, indem zuerst der Cache überprüft wird. Darauf kann in der Regel ein .first()
oder folgen .takeFirst()
, um unnötige Arbeiten zu vermeiden.
http://blog.danlew.net/2015/06/22/loading-data-from-multiple-sources-with-rxjava/
concatMapEager
funktioniert ähnlich, abonniert jedoch so viele wie möglich (plattformabhängig), wird jedoch erst ausgegeben, wenn der vorherige Observable
Vorgang abgeschlossen ist. Perfekt, wenn Sie viel Parallelverarbeitung durchführen müssen, aber (im Gegensatz zu flatMap) die ursprüngliche Reihenfolge beibehalten möchten.
switchMap
wird das letzte abonnieren, auf das Observable
es trifft, und sich von allen vorherigen abmelden Observable
. Dies ist perfekt für Fälle wie Suchvorschläge: Sobald ein Benutzer seine Suchanfrage geändert hat, ist die alte Anfrage nicht mehr von Interesse, daher wird sie abgemeldet, und ein gut erzogener Api-Endpunkt bricht die Netzwerkanfrage ab.Wenn Sie Observable
s zurückgeben, die keinen subscribeOn
anderen Thread haben, verhalten sich alle oben genannten Methoden möglicherweise ähnlich. Das interessante und nützliche Verhalten tritt auf, wenn Sie den verschachtelten Observable
s erlauben , auf ihre eigenen Threads zu reagieren. Dann können Sie viele Vorteile aus der parallelen Verarbeitung ziehen und sich intelligent von Observable
s abmelden oder nicht abonnieren , die Ihre Subscriber
s nicht interessieren
amb
kann auch von Interesse sein. Bei einer beliebigen Anzahl von Observable
s werden dieselben Elemente ausgegeben, die der erste Observable
, der etwas ausgibt, ausgibt. Dies kann nützlich sein, wenn Sie mehrere Quellen haben, die dasselbe zurückgeben könnten / sollten und Leistung wünschen. Beispiel: Sortieren, Sie können amb
eine schnelle Sortierung mit einer Zusammenführungssortierung durchführen und die schnellere verwenden.If you are returning Observables that don't subscribeOn another thread, all of the above methods may behave much the same.
- Jede Erklärung, die switchMap vs flatMap
mir zuvor begegnet ist, hat diesen wichtigen Aspekt übersehen, jetzt ist alles klarer. Danke dir.
switchMap wurde einmal flatMapLatest genannt in RxJS 4 .
Grundsätzlich werden nur die Ereignisse aus dem neuesten Observable weitergegeben und das vorherige abgemeldet.
Map, FlatMap, ConcatMap und SwitchMap wenden eine Funktion an oder ändern die von einem Observable ausgegebenen Daten.
Map ändert jedes von einer beobachtbaren Quelle ausgegebene Element und gibt das geänderte Element aus.
FlatMap, SwitchMap und ConcatMap wenden ebenfalls eine Funktion auf jedes ausgegebene Element an. Anstatt das geänderte Element zurückzugeben, wird das Observable selbst zurückgegeben, das erneut Daten ausgeben kann.
FlatMap- und ConcatMap- Arbeit ist ziemlich gleich. Sie führen Elemente zusammen, die von mehreren Observables ausgegeben wurden, und geben eine einzelne Observable zurück.
Wenn Sie nach einem Beispielcode suchen
/**
* 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);
}
Weitere Beispiele finden Sie hier https://github.com/politrons/reactive
switchMap
mit flatMap
wird es funktioniert genau gleich.
Hier ist das eine weitere - 101 Zeilen lange Beispiel . Das erklärt die Sache für mich.
Wie gesagt: Es wird das letzte beobachtbare (das langsamste, wenn Sie so wollen) und ignoriert den Rest.
Als Ergebnis:
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
Sie sehen, das A wurde ignoriert.