¿Cuál es la diferencia entre flatmap y switchmap en RxJava?

La definición de rxjava doc de switchmap es bastante vaga y se vincula a la misma página que flatmap. ¿Cuál es la diferencia entre los dos operadores?

De acuerdo con la documentación ( http://reactivex.io/documentation/operators/flatmap.html )

el switchMap es como el flatMap , pero solo emitirá elementos desde el nuevo observable hasta que se emita un nuevo evento desde la fuente observable.

El diagtwig de mármol lo muestra bien. Observe la diferencia en los diagtwigs:

En switchMap la segunda emisión original ( mármol verde ) no emite su segunda emisión mapeada ( casilla verde ), ya que la tercera emisión original ( mármol azul ) ha comenzado y ya emitió su primera emisión mapeada ( diamante azul ). En otras palabras, solo ocurre la primera de las dos emisiones verdes asignadas ; no se emite ningún cuadrado verde porque el diamante azul lo golpeó.

En flatMap , se flatMap todos los resultados asignados, incluso si están “obsoletos”. En otras palabras, tanto la primera como la segunda de las emisiones verdes mapeadas suceden: se habría emitido un cuadrado verde (si usaban una función de mapa consistente, ya que no lo hicieron, se ve el segundo diamante verde, aunque se emite después el primer diamante azul)

switchMap en switchMap si el observable original emite algo nuevo, las emisiones anteriores ya no producen observables mapeados; esta es una forma efectiva de evitar resultados obsoletos

mapa plano

en switchMap si el observable original emite algo nuevo, las emisiones anteriores ya no producen observables mapeados; esta es una forma efectiva de evitar resultados obsoletos

Me encontré con esto al implementar “búsqueda instantánea”, es decir, cuando el usuario escribe en un cuadro de texto, y los resultados aparecen casi en tiempo real con cada golpe de tecla. La solución parece ser:

  1. Tener un tema, como PublishSubject of String
  2. En el cuadro de texto, cambie la callback, invoque .onNext (texto)
  3. aplicar .debounce filter para limitar las consultas del servidor
  4. aplicar .switchMap para realizar una consulta del servidor – tomando el término de búsqueda y devolviendo Observable of SearchResponse
  5. aplicar .subscribe con un método que consume SearchResponse y actualiza la UI.

Con flatMap, los resultados de la búsqueda pueden ser obsoletos, ya que las respuestas de búsqueda pueden volver a estar desordenadas. Para solucionar esto, se debe usar switchMap, ya que garantiza que se anule la suscripción de un antiguo observable una vez que se proporcione uno más nuevo.

Por lo tanto, en resumen, flatMap se debe usar cuando todos los resultados importan, independientemente de su tiempo, y se debe usar switchMap cuando solo sean relevantes los resultados del último Observable.

Ninguna discusión de flatMap está completa sin comparar y contrastar con switchMap , concatMap y concatMapEager .

Todos estos métodos toman un Func1 que transforma el flujo en Observable que luego se emiten; la diferencia es cuando los Observable devueltos se suscriben y dan de baja, y si y cuando esas emisiones de esos Observable son emitidas por el operador ____Map en cuestión.

  • flatMap suscribe a tantos Observable emitidos como sea posible. (Es un número dependiente de la plataforma, es decir, un número menor en Android) Úselo cuando la orden NO sea importante y desee emisiones lo antes posible.
  • concatMap suscribe al primer Observable y solo se suscribe al siguiente Observable cuando el anterior se haya completado. Úselo cuando el orden sea importante y desee conservar recursos. Un ejemplo perfecto es aplazar una llamada de red comprobando primero la memoria caché. Suele ser seguido por .first() o .takeFirst() para evitar hacer un trabajo innecesario.

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

  • concatMapEager funciona de manera similar, pero se suscribe a la mayor cantidad posible (depende de la plataforma) pero solo se emitirá una vez que se haya completado el Observable anterior. Perfecto cuando tiene que realizar un gran procesamiento en paralelo, pero (a diferencia de flatMap) desea mantener el orden original.

  • switchMap se suscribirá al último Observable que encuentre y se dará de baja de todos los Observable anteriores. Esto es perfecto para casos como sugerencias de búsqueda: una vez que un usuario ha cambiado su consulta de búsqueda, la solicitud anterior ya no tiene ningún interés, por lo que se cancela la suscripción, y un punto final Api con buen comportamiento cancelará la solicitud de red.

Si devuelve Observable que no se subscribeOn otro hilo, todos los métodos anteriores pueden comportarse de manera similar. El comportamiento interesante y útil surge cuando permite que los Observable nesteds actúen sobre sus propios hilos. Entonces puede obtener muchos beneficios del procesamiento en paralelo, y darse de baja de manera inteligente o no subscribirse de Observable s que no interesan a su Subscriber .

  • amb también puede ser de interés. Dado cualquier número de Observable , emite los mismos elementos que el primer Observable que emite algo emite. Eso podría ser útil cuando tienes varias fonts que podrían / ​​deberían devolver lo mismo y quieres rendimiento. Por ejemplo, ordenar, puede ordenar de forma rápida con un tipo de fusión y usar el que sea más rápido.

switchMap una vez se llamó flatMapLatest en RxJS 4.

Básicamente solo pasa los eventos del último Observable y anula la suscripción del anterior.

Si estás buscando un código de ejemplo

 /** * We switch from original item to a new observable just using switchMap. * It´sa 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); } 

Puedes ver más ejemplos aquí https://github.com/politrons/reactive

Aquí está el otro: 101 líneas de largo ejemplo . Eso explica el problema para mí.

Como se dijo: obtiene el último observable (el más lento si se quiere) e ignora el rest.

Como resultado:

 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 

Ves que A fue ignorada.

Intereting Posts