В чем разница между flatmap и switchmap в RxJava?


The rxjava док определение switchmap довольно расплывчато и оно ссылается на та же страница как flatmap. В чем разница между двумя операторами?

6 119

6 ответов:

согласно документации (http://reactivex.io/documentation/operators/flatmap.html)

the switchMap Как flatMap,но он будет излучать только элементы из нового наблюдаемого, пока новое событие не будет излучено из источника наблюдаемого.

мраморная диаграмма показывает это хорошо. Обратите внимание на разницу в схемах:

на switchMap второй оригинал выбросов (зеленый мрамор) не испускает его второй mapped выбросов (зеленый квадрат), начиная с третьего оригинал выбросов (голубой мрамор) начался и уже испустил свой первый mapped выбросов (голубой бриллиант). Другими словами, только первый два mapped зеленые излучения случаются; никакой зеленый квадрат не испущен потому что голубой Диамант побил его.

на flatMap, все отображается результаты будут испущены, даже если они "несвежие". Другими словами,и первый и второй mapped зеленые выбросы происходят -- a зеленый квадрат был бы испущен (если бы они использовали согласованную функцию карты; поскольку они этого не сделали, вы видите второй зеленый алмаз, даже если он испускается после the первый синий Алмаз)

switchMap in switchMap if the original observable emits something new, previous emissions no longer produce mapped observables; this is an effective way to avoid stale results

flatMap

in switchMap if the original observable emits something new, previous emissions no longer produce mapped observables; this is an effective way to avoi stale results

Я столкнулся с этим при реализации "мгновенного поиска" -т. е. когда пользователь вводит текстовое поле, и результаты появляются в режиме реального времени с каждым нажатием клавиши. Решение кажется:

  1. есть тема, например PublishSubject строки
  2. в текстовом поле изменить обратный вызов, вызвать .наследующей(текст)
  3. применить .отменить фильтр для ограничения скорости запросов сервера
  4. применить .switchMap для выполнения запроса сервера-взятие поискового запроса и возврат Наблюдаемый SearchResponse
  5. применить .подписка с помощью метода, который использует SearchResponse и обновляет пользовательский интерфейс.

с flatMap Результаты поиска могут быть устаревшими, потому что ответы на поиск могут вернуться из строя. Чтобы исправить это, switchMap следует использовать, так как он гарантирует, что старый observable отменяется, как только предоставляется новый.

таким образом, в целом, flatMap следует использовать, когда все результаты имеют значение, независимо от их времени, и switchMap следует использовать, когда только результаты из последнего наблюдаемого вещества.

ни одно обсуждение flatMap не является полным без сравнения и контрастирования с switchMap,concatMap и concatMapEager.

все эти методы взять Func1, которые преобразуют поток в Observables, которые затем излучаются; разница заключается в том, когда возвращается Observables подписаны и отписаны, и если и когда те выбросы тех Observable s испускаются ____Map оператор в вопрос.

  • flatMap подписывается на столько же испущенных Observables, насколько это возможно. (Это номер, зависящий от платформы. т. е. более низкое число на 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 он встречает и отписывается от всех предыдущих Observables. это идеально подходит для таких случаев, как поиск-предложения: как только пользователь изменил свой поисковый запрос, старый запрос больше не представляет никакого интереса, поэтому он отписывается, и хорошо себя ведет конечная точка Api отменит сетевой запрос.

если вы возвращаете Observable s, что не subscribeOn другой поток, все вышеперечисленные методы могут вести себя так же. Интересное и полезное поведение появляется, когда вы разрешаете вложенные Observables, чтобы действовать на своих собственных потоках. Тогда вы можете получить много преимуществ от параллельной обработки и разумно отказаться от подписки или не подписываться на Observables, которые не интересуют ваш Subscriber s

  • amb также может представлять интерес. Учитывая любое количество Observable s он выдает те же элементы, что и первый Observable чтобы испустить что-нибудь испускает. Это может быть полезно, когда вы есть несколько источников, которые могут/должны возвращать одно и то же, и вы хотите производительность. например, сортировка, вы можете amb быстрая сортировка со слиянием-сортировка и использование в зависимости от того, что было быстрее.

switchMapкогда-то называлиflatMapLatest в RxJS 4.

Он в основном просто передает события из последний наблюдаем и отписываемся от предыдущего.

Если вы ищете пример кода

/**
 * 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

вот еще одна-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 был проигнорирован.