Debe haberse enfrentado a una situación en Android en la que deseaba realizar varias llamadas de red en paralelo para obtener los datos simultáneamente. Entonces, una forma de implementar esto es con la ayuda de Kotlin Coroutines , que se explica en este artículo ( Llamadas paralelas de red múltiple usando Kotlin Coroutines ). Pero hoy veremos las diferentes formas de hacerlo con la ayuda del Operador Zip de Kotlin Flow . Este enfoque parece menos complicado, más fácil y limpio, y viene con una función integrada de manejo de errores de API del propio flujo.
Comprender el operador Zip en Kotlin Flow
Es un operador de flujo de Kotlin que emite un solo elemento/valor después de combinar la emisión de dos colecciones de flujo a través de una función específica. Esto significa que comprime los valores del flujo actual con otro flujo y los emite como un elemento/valor único para cada combinación en función de los resultados de esta función específica. Entendamos con el ejemplo.
Entonces, en este ejemplo, supongamos que las dos primeras líneas negras son dos colecciones de flujo diferentes que emiten valores diferentes. Y al comprimirlos, en realidad estamos obteniendo estos valores como un único resultado en una sola devolución de llamada simultáneamente. Ahora, veamos cómo usarlo con llamadas de red paralela
En este ejemplo, seguimos la arquitectura MVVM y usamos una clase de recurso que representa diferentes estados de la interfaz de usuario, como carga, éxito, error para envolver nuestros datos finales.
Ahora, supongamos que necesitamos mostrar un texto «Hola Geeks» en la pantalla, pero obtendremos este texto en dos partes, es decir, «Hola» y «Geeks» por separado de dos llamadas de red separadas. Por lo tanto, necesitamos una forma en la que podamos obtener ambos textos simultáneamente a medida que finalizan ambas llamadas API, lo que significa que el resultado de ambas llamadas API simultáneamente en una única y misma devolución de llamada. Y para obtener el resultado de ambas llamadas API simultáneamente, comprimiremos el resultado de ambas llamadas API usando el operador zip y luego devolveremos el resultado de ambas API como un solo elemento/texto de una función lambda del operador zip para que podamos recogerlo en la función de recogida. Estamos suponiendo que:
getFirstText() : Obtendrá el primer texto, es decir, «Hola» de la primera llamada de red
getSecondText() : Obtendrá el segundo texto, es decir, «Geeks» de la segunda llamada de red
Ver modelo
Veamos cómo hacerlo exactamente en ViewModel:
Kotlin
class ExampleViewModel( private val exampleRepo: ExampleRepo ) : ViewModel() { // we'll post result in this MutableLiveData private var _exampleText = MutableLiveData<Resource<String>>() // we can observe this LiveData from UI val exampleText : LiveData<Resource<String>> = _exampleText init { // Putting 'fetchBothText()' function in // init{} block so that it'll // automatically get called once this viewmodel // will get initialized in activity/fragment fetchBothText() } private fun fetchBothText() = viewModelScope.launch { // posting loading state in this livedata for UI _exampleText.postValue(Resource.Loading()) exampleRepo.getFirstText() // Here, we're calling zip function .zip(exampleRepo.getSecondText()) { firstText, secondText -> // Here we're getting result of both network calls // i.e. firstText & secondText // Just returning both the values by simply // adding them in this lambda // function of zip and then we'll get this // result in collect function // Whatever we returns from here by specifying it, // we can collect that in collect function return@zip "$firstText $secondText" } // Making it run on Dispathers.IO // i.e. input/output thread .flowOn(Dispatchers.IO) .catch { e -> // Here, we'll get an exception if // any failure occures in network calls // So, we're simply posting error message _exampleText.postValue(Resource.Error(e.toString())) } .collect { it -> // Now here we can collect that value // which we have passed in lambda // function of zip i.e. "$firstText $secondText" // Now simply returning result value as a single // item/value by wrapping it in Resource.Success class _exampleText.postValue(Resource.Success(it)) } } }
Llamamos a las llamadas a la API getFirstText() y getSecondText() en paralelo con la ayuda de la función zip y obtenemos los resultados de ambas llamadas de red en la misma devolución de llamada cuando se completan ambas llamadas de red. En este caso, básicamente estamos agregando ambos textos (es decir, agregando ‘primerTexto’ con ‘segundoTexto’ para que sea un solo texto Hello Geeks) y luego simplemente devolvemos este resultado especificado (es decir, «$primerTexto $segundoTexto» que dará Hola Geeks”) de la función lambda del operador zip para que podamos recopilarlo en la función de recopilación de flujo. Y luego, desde la función de recopilación, simplemente envolvemos el resultado único con Resource.Success y lo publicamos en mutable livedata (_exampleText) para que la interfaz de usuario pueda observar esta actualización y mostrarla en la pantalla.
Eso es todo. hemos ejecutado con éxito ambas llamadas de red en paralelo mediante el uso del operador Zip y obtuvimos el resultado de ambas en una sola devolución de llamada cuando ambas llamadas de red se completaron. Entonces, así es como podemos simplemente usar el operador Zip para ejecutar llamadas de red paralelas para que podamos obtener el resultado de ambas al mismo tiempo en la misma y única devolución de llamada.
Publicación traducida automáticamente
Artículo escrito por haiderfaizan732 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA