Combinando los resultados de múltiples observables

Estoy tratando de lograr algo como esto: – Hacer dos llamadas API diferentes y combinar los resultados en una list. El resultado de cada llamada es un HashMap y tengo una function para convertirlo en una list. Lo que trato de hacer ahora es combinar las lists en una, pero estoy teniendo dificultades.

Este es el aspecto de mi service Retrofit:

@GET("data/price?fsym=ETH") fun getETHRates(@Query("tsyms") tsyms : String) : Single<HashMap<String, Double>> @GET("data/price?fsym=BTC") fun getBTCRates(@Query("tsyms") tsyms: String) : Single<HashMap<String, Double>> 

He podido realizar las llamadas por separado y transformar el resultado en una list (corrígeme si esto se puede hacer mejor) de esta manera:

  val btcRates: Single<List<Currency>> = cryptoApi.getBTCRates(countries) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .flatMap { result: HashMap<String, Double> -> return@flatMap Single.just(createCurrencyObjects ("BTC", result)) } val ethRates: Single<List<Currency>> = cryptoApi.getETHRates(countries) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .flatMap { result: HashMap<String, Double> -> return@flatMap Single.just(createCurrencyObjects("ETH", result)) } 

Esta es la function que transforma el resultado en una list:

  fun createCurrencyObjects(from: String, map: HashMap<String, Double>): List<Currency> { val list = ArrayList<Currency>(0) for (key in map.keys) { val amount: Double? = map.get(key) list.add(Currency(0, from, key, amount!!)) } return list; } 

Lo que quiero hacer ahora es combinar las lists de ambas llamadas y luego savelas en una database. ¿Cómo hago esta combinación con RxJava?

Intenté algo así, pero sigo recibiendo posts de error:

  val apiCall: Disposable = Observable.concat(ethRates, btcRates) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .doOnNext { values: List<Currency> -> run { App.database?.currencyDao()?.insertAllCurrencies(values) } } .doOnError { e -> e.printStackTrace() } .subscribe(); 

Usando el operador zip puedes combinar el resultado de ambos Single y aplicar una function transformadora que devuelve una list

 Single.zip( rates1, rates2, BiFunction<List<Currency>, List<Currency>, List<Currency>> { x, y -> // return your list } ).doOnSuccess { list -> // save your data } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) 

La respuesta de gyosida es correcta. Aquí hay otro ejemplo que muestra un uso genérico de Zip:

  val single1 = Single.just(mutableListOf("one", "two", "three")) val single2 = Single.just(mutableListOf("four", "five", "six")) val single = Single.zip(single1, single2, BiFunction { a: MutableList<String>, b: MutableList<String> -> a.addAll(b) return@BiFunction a }) 

Feliz encoding!

  • Adaptador personalizado de Moshi con RxAndroid & Retrofit & Kotlin
  • Reactor Spring 5 - Emisión de elementos cada 1 segundo
  • Cómo get el valor del ObservableField en android
  • ¿Cómo podemos implementar Observable.flatMapCompletable?
  • Cómo pasar nulo a un Observable con tipo anulable en RxJava 2 y Kotlin
  • RxJava 2 requiere un tipo de retorno Observable diferente de RxJava 1 (Kotlin)
  • OnComplete nunca se llamó con toSortedList () y groupBy ()
  • Obteniendo una IllegalStateException al usar la API People de Google a pesar de suscribirse a otro hilo usando RxJava
  • Usando RxJava con Handler, restablece Message.what value
  • RxJava Valor pnetworkingeterminado para throttleFirst
  • Tipo de devolución diferente en RxJava 2 (actualización desde RxJava1)