es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Rxjava2 y Retrofit: múltiples llamadas se devuelven como una lista.

Las llamadas a la API deben realizarse aproximadamente unas 30 veces y solo difieren en un parámetro:

https://api.website.com/getProducts?category_id=10
https://api.website.com/getProducts?category_id=11

Estas llamadas responden con un límite de 100 productos por llamada. Si una categoría tiene más productos, necesito añadir un parámetro de desplazamiento. La siguiente llamada me dará el subconjunto de productos del 101 al 200. También se proporciona un total en la respuesta para saber cuándo parar.

https://api.website.com/getProducts?category_id=10&offset=100
https://api.website.com/getProducts?category_id=10&offset=200 <--la categoría tiene 260 productos, paro aquí.

Puedo hacer las llamadas iniciales (sin desplazamiento) y las llamadas con desplazamiento fácilmente con Retrofit. Pero con Retrofit no puedo registrar ninguna devolución de llamada cuando todas las llamadas hayan terminado, ni devolver los datos como una lista para actualizar mi interfaz de usuario solo una vez.

Así que quiero intentarlo con RxJava2. Ya he logrado lo mismo con Retrofit (devolviendo un Observable después de cada llamada principal o llamada con desplazamiento).

private Observable<SearchResponse> search(int category, int offset) {
    Observable<SearchResponse> call = retrofitSearchService.search(category, offset);

    return call.flatMap(new Function<SearchResponse, ObservableSource<?>>() {
        @Override
        public ObservableSource<SearchResponse> apply(@NonNull SearchResponse searchResponse) throws Exception {

            if (searchResponse.getTotal() > (searchResponse.getOffset() + searchResponse.getLimit())) {
                search(category, searchResponse.getOffset() + 100); <--recursión aquí
            }
            return Observable.just(searchResponse);
        }
    }).toList().toObservable()
            .cast(SearchResponse.class);
}

Devolver cada respuesta como una sola hace que mi interfaz de usuario se actualice constantemente (Android LiveData).

Aún quiero:
1. Devolver una lista completa de todas las categorías y sus hijos, si los tienen.
2. Obtener una sola devolución de llamada cuando se realicen todas las solicitudes.

Esto parece prometedor (https://stackoverflow.com/questions/31246088/how-to-do-recursive-observable-call-in-rxjava). Pero no logro entenderlo.

Si puedes, por favor, evita el uso de lambda. Function, Consumer, Subscriber me resultan más claros. ¡Genial!

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Uso de RxJava2 para realizar llamadas a API

    En este escenario, tenemos que realizar alrededor de 30 llamadas a API que solo varían en un parámetro. Podemos lograr esto fácilmente usando Retrofit. Sin embargo, una vez que todas las llamadas se han completado, no podemos registrar los callbacks de Retrofit. Y tampoco podemos devolver los datos como una lista para actualizar la interfaz de usuario solo una vez.

    En este caso, podemos usar RxJava2 para realizar las llamadas a la API. Podemos devolver cada respuesta como una lista, pero eso haría que nuestra interfaz de usuario se actualice de forma frenética.

    Para resolver este problema, estamos realizando llamadas observables recursivas en RxJava2. A continuación se muestra el código:

    private Observable<><searchresponse>> search(int category, int offset) {
            return retrofitSearchService.search(category, offset)
                    .flatMap((Function<searchresponse,></searchresponse,><><searchresponse>>>) searchResponse -> {
                        if (searchResponse.getTotal() > (searchResponse.getOffset() + searchResponse.getLimit())) {
                            return search(category, searchResponse.getOffset() + 100)
                                    .map(searchResponses -> {
                                        searchResponses.add(0, searchResponse);
                                        return searchResponses;
                                    });
                        } else {
                            return Observable.just(Collections.singletonList(searchResponse));
                        }
                    })
                    .flatMapObservable(Observable::fromIterable)
                    .toList()
                    .toObservable();
        }
    

    Aquí, estamos devolviendo cada respuesta de búsqueda como una lista. Y después de todas las llamadas recursivas, tendremos una lista de todas las categorías e hijos. Y obtendremos un callback cuando se realicen todas las solicitudes.

    Estamos utilizando el operador flatMap para llamar a la API de forma recursiva. Y estamos añadiendo cada respuesta en la lista. Si no hay más datos, devolvemos una lista con solo una respuesta de búsqueda.

    Finalmente, estamos convirtiendo esto en un observable y devolviéndolo.

    Tenga en cuenta que estamos utilizando lambda en lugar de Function, Consumer o Subscriber para una mejor legibilidad.

    Conclusión

    En este escenario, hemos visto cómo realizar alrededor de 30 llamadas a API con diferentes parámetros utilizando Retrofit y RxJava2. También podemos obtener un único callback cuando se realizan todas las solicitudes.

Comments are closed.