multiple api request using retrofit and rx java
Asked Answered
F

3

10

I am new to android and I have a scenario where I want to get get data from multiple api. Let suppose api_a, api_b, api_c, api_d. These api are independent of each other but I want to show data from these api in a mix Recycler View (horizontal and vertical). So I want to make these api call in such a manner so that I can get every api data at a time so that i can display in recycler view. I already using retrofit 2 but for that I had to chain them one by one which is very lengthy and I think this is not a feasible approach. I know little bit about RX JAVA ,but I only know how to make one request at a time. Please help

Forestaysail answered 30/6, 2018 at 7:7 Comment(3)
Try the accepted answer - #36401693Fantasm
suppose the result of these 4 api gives me 4 different string which are independent of each other can i get that?Forestaysail
check it out github.com/fakefacebook/Retrofit-2-with-Rxjava-multiple-requestHopkins
B
25

There are at least 2 ways to achieve this -

1) Using RxJava Zip operator (for parallel requests)

Get all the observables

Observable<ResponseType1> observable1 = retrofit.getApi_a();
Observable<ResponseType2> observable2 = retrofit.getApi_b();
Observable<ResponseType3> observable3 = retrofit.getApi_c();

Zip the observables to get a final observable

Observable<List<String>> result = 
Observable.zip(observable1.subscribeOn(Schedulers.io()), observable2.subscribeOn(Schedulers
            .io()), observable3.subscribeOn(Schedulers.io()), new Function3<ResponseType1, ResponseType2, ResponseType3, List<String>>() {
    @Override
    public List<String> apply(ResponseType1 type1, ResponseType2 type2, ResponseType3 type3) {
        List<String> list = new ArrayList();
        list.add(type1.data);
        list.add(type2.data);
        list.add(type3.data);
        return list;
    }
});

now subscribe on the resultant observable

result.observeOn(AndroidSchedulers.mainThread())
            .subscribeWith(new Observer<List<String>>() {
                @Override
                public void onSubscribe(Disposable d) {

                }

                @Override
                public void onNext(List<String> s) {
                    Log.d(TAG, "s is the list with all the data");
                }

                @Override
                public void onError(Throwable e) {
                    Log.e(TAG, e.getMessage());
                }

                @Override
                public void onComplete() {

                }
            });

2) Using RxJava flatMap() operator. (To request serially one after another)

This is simple chaining of requests

    List<String> result = new ArrayList<>();
    Disposable disposable = retrofit.getApi_a()
            .subscribeOn(Schedulers.io())
            .flatMap((Function<ResponseType1, ObservableSource<ResponseType2>>) response1 -> {
                result.add(response1.data);
                return retrofit.getApi_b();
            })
            .flatMap((Function<ResponseType2, ObservableSource<ResponseType3>>) response2 -> {
                result.add(response2.data);
                return retrofit.getApi_c();
            })
            .map(response3 -> {
                result.add(response3.data);
                return response3;
            })
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeWith(new DisposableObserver<Response3>() {

                @Override
                public void onNext(Response3 response3) {
                    Log.d(TAG, "result variable will have all the data");
                }

                @Override
                public void onError(Throwable e) {
                    Log.e(TAG, e.getMessage());
                }

                @Override
                public void onComplete() {

                }
            });
Bijection answered 10/7, 2018 at 9:43 Comment(1)
What happend if any one api fails in Zip or Flatmap ?Rana
B
0

For combining multiple Observables you may want to consider the Merge operator. This would allow you to combine the stream of multiple requests into a single Observable.

Merge will interleave them as they are emitted. If sequence matters, there is also Concat which will emit from each Observable before continuing with the next.

Rx Doc

Beaton answered 1/7, 2018 at 20:56 Comment(4)
actually my requirement is not to merge them but to get separate data but i want the to execute parallel and not one by oneForestaysail
I see, using Observables with Retrofit your requests will be asynchronous. You can fire off each API request and handle the responses with OnNext as they return.Beaton
can you show give me some link which retrofit and rx java is used for multiple api callForestaysail
What is I have more than 4 requests to combine? Merge accepts only 4Respect
S
0

Merge operator combines multiple observable into one

Set up Base URL of API:

Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(Constants.BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(oktHttpClient.build())
                    .build();

Now setup two observables for the two network requests:

Observable<JsonElement> Observable1 = ApiClient.getApiService().getApi_1();

Observable<JsonElement> Observable2 = ApiClient.getApiService().getApi_2();

Now we use RxJava's mergemethod to combine our two Observables:

Observable.merge(Observable1, Observable2 )
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<JsonElement>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(JsonElement value) {
                        Log.d("RESPONSE", "onNext:=======" + value);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {
                        Log.d("RESPONSE", "DONE==========");
                    }
                });
Swinney answered 11/2, 2020 at 7:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.