Rxjava док определение switchmap является довольно расплывчатым и ссылки на той же странице , как flatmap. В чем разница между двумя операторами?
Rxjava док определение switchmap является довольно расплывчатым и ссылки на той же странице , как flatmap. В чем разница между двумя операторами?
Ответы:
Согласно документации ( http://reactivex.io/documentation/operators/flatmap.html )
switchMap
подобно flatMap
, но он будет издавать только элементы из новых наблюдаемых , пока новое событие не излучается из источника наблюдаемого.
Мраморная диаграмма хорошо это показывает. Обратите внимание на разницу в диаграммах:
Во switchMap
втором исходном излучении ( зеленый мрамор ) не испускается его второе сопоставленное излучение ( зеленый квадрат ), поскольку третье исходное излучение ( синий мрамор ) уже началось и уже выпустило свое первое сопоставленное излучение ( синий ромб ). Другими словами, происходит только первое из двух нанесенных на карту зеленых выбросов; зеленый квадрат не испускается, потому что синий бриллиант побеждает его.
В flatMap
, будут отображены все сопоставленные результаты, даже если они «устаревшие». Другими словами, как первый и второй из отображенных зеленых выбросов произойдет - это зеленый квадрат бы уже вылетать (если они использовали последовательную функцию карты, так как они не сделали, вы увидите второй зеленый алмаз, даже если он излучается после первый голубой бриллиант)
flatMap
.map(func).switch
, но это то же самое, что и .switchMap(func)
.
Я сталкивался с этим при реализации «мгновенного поиска» - то есть когда пользователь вводит текстовое поле, и результаты отображаются почти в реальном времени с каждым нажатием клавиши. Решение, кажется, заключается в следующем:
С flatMap результаты поиска могут устареть, потому что ответы могут возвращаться не в порядке. Чтобы исправить это, следует использовать switchMap, так как он гарантирует, что старая наблюдаемая отписывается после того, как предоставлена более новая.
Таким образом, в итоге, flatMap следует использовать, когда все результаты имеют значение, независимо от их времени, и switchMap следует использовать, когда только результаты из последнего наблюдаемого значения.
Ни одно обсуждение flatMap не будет полным без сравнения и противопоставления switchMap
, concatMap
и concatMapEager
.
Все эти методы принимают a, Func1
который преобразует поток в Observable
s, которые затем испускаются; разница заключается в том, когда возвращенные Observable
s подписаны и отписаны, и если и когда эти выбросы этих Observable
s испускаются соответствующим ____Map
оператором.
flatMap
подписывается на максимально возможное количество Observable
s. (Это число зависит от платформы. Например, более низкое число на Android) Используйте это, когда порядок не важен, и вы хотите выбросы как можно скорее.concatMap
подписывается на первый Observable
и подписывается только на следующий, Observable
когда предыдущий завершен. Используйте это, когда порядок важен, и вы хотите сохранить ресурсы. Прекрасный пример - отложить сетевой вызов, проверив сначала кеш. Обычно это может сопровождаться .first()
или, .takeFirst()
чтобы избежать ненужной работы.
http://blog.danlew.net/2015/06/22/loading-data-from-multiple-sources-with-rxjava/
concatMapEager
работает почти так же, но подписывается на максимально возможное количество (зависит от платформы), но издает только после завершения предыдущего Observable
. Идеально, когда у вас много параллельной обработки, которую нужно выполнить, но (в отличие от flatMap) вы хотите сохранить исходный порядок.
switchMap
подпишется на последнюю Observable
встречу и отписаться от всех предыдущих Observable
с. Это идеально подходит для случаев, подобных поисковым предложениям: как только пользователь изменил свой поисковый запрос, старый запрос больше не представляет интереса, поэтому он отменяется, и конечная точка Api с хорошим поведением отменяет сетевой запрос.Если вы возвращаете Observable
s, которые не являются subscribeOn
другим потоком, все вышеперечисленные методы могут вести себя примерно одинаково. Интересное и полезное поведение возникает, когда вы позволяете вложенным Observable
элементам действовать в своих собственных потоках. Тогда вы можете получить получить много преимуществ от параллельной обработки, и разумно отписки или не подписываться от Observable
S , которые не интересуют ваши Subscriber
S
amb
также может представлять интерес. При любом количестве Observable
s он испускает те же элементы, что и первый, Observable
испускающий что-либо. Это может быть полезно, когда у вас есть несколько источников, которые могут / должны возвращать одно и то же, и вы хотите повысить производительность. например, сортировка, вы можете amb
быстро сортировать с помощью сортировки слиянием и использовать тот, который был быстрее.If you are returning Observables that don't subscribeOn another thread, all of the above methods may behave much the same.
- каждое объяснение, с которым switchMap vs flatMap
я сталкивался раньше, упускало этот важный аспект, теперь все проясняется. Спасибо.
switchMap когда-то назывался flatMapLatest в RxJS 4.
Он в основном просто передает события из последней Observable и отписывается от предыдущего.
Map, FlatMap, ConcatMap и SwitchMap применяют функцию или изменяют данные, испускаемые Observable.
Карта изменяет каждый элемент, испускаемый наблюдаемой источником, и испускает измененный элемент.
FlatMap, SwitchMap и ConcatMap также применяют функцию к каждому испускаемому элементу, но вместо возврата измененного элемента он возвращает сам Observable, который может снова выдавать данные.
Работа FlatMap и ConcatMap практически одинакова. Они объединяют элементы, испускаемые несколькими наблюдаемыми, и возвращают одну наблюдаемую.
Если вы ищете пример кода
/**
* 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);
}
Вы можете увидеть больше примеров здесь https://github.com/politrons/reactive
switchMap
с flatMap
он будет работать точно так же.
Вот еще один пример - 101 строка . Это объясняет это для меня.
Как было сказано: он получает последнее наблюдаемое (самое медленное, если хотите) и игнорирует все остальное.
В следствии:
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
Вы видите, что A проигнорировали.