-->

multiple api request using retrofit and rx java

2020-02-05 00:21发布

问题:

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

回答1:

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() {

                }
            });


回答2:

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

  • Merge: http://reactivex.io/documentation/operators/merge.html
  • Concat: http://reactivex.io/documentation/operators/concat.html