STK*_*K90 6 android rx-java dagger-2 retrofit2
我需要通过将多个改造 API 调用链接在一起来创建一个 observable。
我有 2 个服务:ItemService,它只包含项目名称和 id,以及 ItemDetailsService,它包含有关项目的许多其他详细信息,如描述图像等。我正在使用 Retrofit 2 + RxJava + Dagger 2。
项目服务:
@GET("apione/items")
Observable<List<Items>> getItems();
Run Code Online (Sandbox Code Playgroud)
ItemDetailsService:
@GET("apitwo/item/{id}")
Observable<ItemDetail> getItemDetails(@Path("id") int id);
Run Code Online (Sandbox Code Playgroud)
项目 json:
[
{
"id": 1,
"name": "one"
},
{
"id": 2,
"name": "two"
},
{
"id": 3,
"name": "three"
}
]
Run Code Online (Sandbox Code Playgroud)
用于具体项目 ID 的 ItemDetails json:
{
"id": 1,
"image_url": "http://.../1.png",
"description": "description of item one",
"category": "cat_1",
"quantity" 10
}
Run Code Online (Sandbox Code Playgroud)
此外,这 2 个 API 具有不同的基本 URL。那么如何制作一个 Observable 返回带有图像、数量和类别的项目列表呢?
更新
我卡在这里了。这是我的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);
}
}
Run Code Online (Sandbox Code Playgroud)
不明白如何正确制作。如果我只需要关于列表中项目的一些详细信息,而不是 ItemDetail 中的任何内容,我必须做什么?
我只需要将 ItemDetail 中的一些细节添加到 Items 列表中。
如果我理解正确,那么这应该可以满足您的需求:
private Observable<List<ItemDetail>> getItemDetails() {
return service1.getItems()
.flatMap(new Func1<List<Item>, Observable<List<ItemDetail>>>() {
@Override
public Observable<List<ItemDetail>> call(List<Item> items) {
List<Observable<ItemDetail>> detailObservables = new ArrayList<>();
for (Item item : items) {
detailObservables.add(service2.getItemDetails(item.id));
}
return Observable.zip(
detailObservables,
new FuncN<List<ItemDetail>>() {
@Override
public List<ItemDetail> call(Object... args) {
List<ItemDetail> itemDetails = new ArrayList<>();
for (Object arg : args) {
itemDetails.add((ItemDetail) arg);
}
return itemDetails;
}
}
);
}
});
}
Run Code Online (Sandbox Code Playgroud)
请注意,我在这段代码中假设您的getItemDetails方法返回一个对象列表ItemDetail,只是为了代码清晰起见。
说明:我使用flatMap()运算符来处理从第一个服务请求接收到的项目列表,然后为每个项目详细信息 API 请求创建一个 Observable 并将其添加到列表中detailObservables。然后使用该运算符,它基本上启动所有请求并在所有请求完成时zip触发回调。FuncN你必须将 投射Object到ItemDetail那里。
编辑:我在方法名称前面添加了 service1 和 service2 ,以使其更清楚我的意思。