I need to create an observable by chaining together multiple retrofit API calls.
I have 2 services: ItemService which contains only item name and id, and ItemDetailsService which contains many other details about item like description image and etc. I am using Retrofit 2 + RxJava + Dagger 2.
ItemService:
@GET("apione/items")
Observable<List<Items>> getItems();
ItemDetailsService:
@GET("apitwo/item/{id}")
Observable<ItemDetail> getItemDetails(@Path("id") int id);
Items json:
[
{
"id": 1,
"name": "one"
},
{
"id": 2,
"name": "two"
},
{
"id": 3,
"name": "three"
}
]
ItemDetails json for a concret Item id:
{
"id": 1,
"image_url": "http://.../1.png",
"description": "description of item one",
"category": "cat_1",
"quantity" 10
}
Also these 2 API's have different Base URL. So how is it possible to make an Observable wich returns list of items with their image, quantity and category ?
UPDATED
I stucked here. This is my ItemPresenter
public class ItemPresenter extends BasePresenter<ItemView> implements Observer<List<Item>> {
@Inject protected ItemService mItemService;
@Inject protected ItemDetailsService mItemDetailsService;
@Inject
public ItemPresenter() {
}
public void getItems() {
getView().onShowDialog("Loading");
Observable<List<Item>> itemObservables= mItemService.getItems()
.flatMap(new Func1<List<Item>, Observable<ItemDetail>>() {
@Override
public Observable<ItemDetail> call(List<Item> items) {
List<Observable<ItemDetail>> detailObservables = new ArrayList<>();
for (Item item : items) {
detailObservables.add(mItemDetailsService.getItemDetail(item.getId());
}
return Observable.zip(
detailObservables,
args -> {
List<Item> itemDetails = new ArrayList<>();
for (Object arg : args) {
itemDetails.add((Item) arg);
}
return itemDetails;
}
);
}
});
subscribe(detailObservables, this);
}
@Override
public void onCompleted() {
getView().onHideDialog();
getView().onShowToast("Complete");
}
@Override
public void onError(Throwable e) {
getView().onHideDialog();
getView().onShowToast("Error loading " + e.getMessage());
}
@Override
public void onNext(List<Item> items) {
getView().onItems(items);
}
}
Dont understand how to make it correctly. And whar I have to do if I need only few details about items in list, not everething from ItemDetail ?
I only need to add some details from ItemDetail to Items list.
To achieve your goal you should to follow the next algorithm:
List<Item>
;List<Item>
to emit just Item
;Item
you should to request instance of ItemDetail
. As mItemDetailsService.getItemDetails(@Path("id") int id)
return Observable<ItemDetail>
, so you should to use flatMap(...)
for this;Code:
Observable<List<ItemDetail>> detailObservables = mItemService.getItems()
.flatMap(new Func1<List<Item>, Observable<Item>>() {
@Override
public Observable<Item> call(List<Item> items) {
return Observable.from(items);
}
})
.flatMap(new Func1<Item, Observable<ItemDetail>>() {
@Override
public Observable<ItemDetail> call(Item item) {
return mItemDetailsService.getItemDetail(item.getId());
}
}).toList();
If you need for example just image_url instead of whole item detail, you could call:
.map(new Func1<ItemDetail, String>() {
@Override
public String call(Object itemDetail) {
return itemDetail.getImageUrl();
}
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With