Reputation: 201
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
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
Reputation: 1981
CombineLatest work in concurrency mode. If we watch to picture below
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.
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