Arefeh Iravanchi
Arefeh Iravanchi

Reputation: 201

Combining Response of 2 API call by RxJava

I have 2 request with different response that I want to merge response of them together by using RxJava . The request one has response like this :

{
"A":{
"id" : ""
},
"B":{}
}

And the request two has response like this :

{
"A": {
"name" : ""
},
"C" :{}
}

As the final result I want to combine 2 response blocks of API calls with a pattern which includes all fields of 2 response like this :

{
"A" {
"id" : "",
"name" : ""
},

"B" :{},
"C" : {},
}

I use retrofit for my Api calls and Also I know a little about zip and combineLatest operations in RxJava. But I don't know the best way for combining.

Upvotes: 2

Views: 2362

Answers (3)

arungiri_10
arungiri_10

Reputation: 988

You first need to create POJO classes. Let's say DataMain, DataA, DataB, DataC

DataA class (contains id and name):

public class DataA {
    @SerializedName("id")
    private String id;

    @SerializedName("name")
    private String name;

    public String getId() {
        return id;
    }
    public String getName() {
        return name;
    }

    public DataA setName(String name) {
        this.name = name;
        return this;
    }
}

Now DataB class:

public class DataB {
    @SerializedName("bid")
    private String bid;
}

Now DataC class:

public class DataC {
    @SerializedName("cid")
    private String cid;

    public String getCid() {
        return cid;
    }
}

Now comes the DataMain class (contains DataA, dataB, DataC)

public class DataMain {
    @SerializedName("A")
    public DataA dataA;

    @SerializedName("B")
    public DataB dataB;

    @SerializedName("C")
    public DataC dataC;

    public DataA getDataA() {
        return dataA;
    }

    public DataMain setDataA(DataA dataA) {
        this.dataA = dataA;
        return this;
    }

    public DataC getDataC() {
        return dataC;
    }

    public DataMain setDataC(DataC dataC) {
        this.dataC = dataC;
        return this;
    }
}

Based on the JSON structure we have created the POJO classes. Now we will be doing 2 API calls something similar to below

//getApi() - initialization of retrofit
public static DataMainApi getApi() {
    return new Retrofit.Builder()
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .addConverterFactory(GsonConverterFactory.create())
        .baseUrl("your URL")
        .build()
        .create(DataMainApi.class);
}

//Here we will get DataA with id and DataB
public static Observable<DataMain> getData1() {
    return getApi().getDataMain1().subscribeOn(Schedulers.io());
}

//Here we will get DataA with name and DataC
public static Observable<DataMain> getData2() {
    return getApi().getDataMain2().subscribeOn(Schedulers.io());
}

Now we will call the above 2 APIs using Rx-Java

    Observable
        .zip(
            getData1(),
            getData2(),
            (dataMain1, dataMain2) -> dataMain1.setDataA(
                dataMain1.getDataA().setName(dataMain2.getDataA().getName())
            ).setDataC(dataMain2.getDataC())
        )
        .subscribe(
            result -> //Result with combined data,
            error -> error.printStackTrace()
        );

Basically what we are doing is get Data1 (with DataA(id) and DataB) and get Data2(with DataA(name) and DataC), and copying the values to DataMain.

Hope this helps.

Upvotes: 1

Scrobot
Scrobot

Reputation: 1981

CombineLatest work in concurrency mode. If we watch to picture below

description

you can see that you have 2 flows and data combines in next case:

1 combines with A -> result 1A. When the next input value at first thread is 2. Combiner watches at the second thread and sees value A. Combine operation returns value 2A. And so on.

Let's imagine, that we have next case:

        Observable<Integer> producer1 = Observable.just(1, 2, 3, 4 ,5)
                .doOnComplete(() -> {
                    System.out.println("complete");
                });

        Observable<String> producer2 = Observable.just("A", "B", "C", "D", "F");

        System.out.println("combineLatest");
        Observable.combineLatest(producer1, producer2, (i, s) -> i + s)
                .subscribe((result) -> {
                    System.out.println(result);
                }, Throwable::printStackTrace);

This code will output the next thing

combineLatest
complete
5A
5B
5C
5D
5F

Because value 5 is the latest value in the thread. And then it makes last modifications - it's complete(because of just operator).

So, let's resume the first part: if you have the case, when you need to have some concurrency state - you can use combineLatest.

Zip - is merging values in the sequence in which they entered.

enter image description here

And if we watch the same case, but with zip

Observable<Integer> producer1 = Observable.just(1, 2, 3, 4 ,5)
                .doOnComplete(() -> {
                    System.out.println("complete");
                });

        Observable<String> producer2 = Observable.just("A", "B", "C", "D", "F");

        System.out.println("\nzip");
        Observable.zip(producer1, producer2, (i, s) -> i + s)
                .subscribe((result) -> {
                    System.out.println(result);
                }, Throwable::printStackTrace);

The output will be

zip
complete
1A
2B
3C
4D
5F

So, in your case, if you need to merge two models, I recommend you to choose zip operator.

Upvotes: 0

Aditya
Aditya

Reputation: 90

You can use RxJava's zip operator to combine result of two api calls. You will also need to create a DTO object to represent the combination of both the API calls

Upvotes: 0

Related Questions