android - 当我需要前一个服务的结果时,如何使用 RxJava 链接多个改造服务?
问题描述
.
它的目的是检索库存的详细信息。我有 2 项服务,一项用于获取可用库存,另一项为您提供给定库存的详细信息。
先看看我的改造界面
public interface RetrofitApiService {
@GET("inv.svc/availableInventories")
Single<AvailableInventories> getAvailableInventories();
@GET("inv.svc/inventoryDetails")
Single<InventoryDetails> getInventoryDetails(@Query("invName") String invName);
}
这些是改造服务构建的对象:
AvailableInventories
List<InventoryName> inventoryNames
InventoryName
String id
String name
String ref
InventoryDetails
List<InventoryLine> inventoryLines
InventoryLine
String articleRef
String inventoryRef
String conditioning
String CountedStock
String expectedStock
所以我要调用getAvailableInventories()
它将返回一个AvailableInventories
包含 3 的对象InventoryName
(例如)首先我想将它们存储inventoryNames
在 my_database.Inventory_names
InventoryName
String "1"
String "paris-warehouse"
String "az2r8"
InventoryName
String "2"
String "mila-warehouse"
String "d8f5s"
InventoryName
String "3"
String "berlin-warehouse"
String "g8z3d"
那么我将不得不打电话
getInventoryDetails("az2r8")
store in database, table inventory_line_details
getInventoryDetails("d8f5s")
store in database, table inventory_line_details
getInventoryDetails("g8z3d")
store in database, inventory_line_details
最后我需要重定向到另一个屏幕。
我怎样才能在 RxJava 中做到这一点?以前我会使用简单的 android asynctasks 并使它们非异步使用.execute.get()
但是似乎我不能用 rx java 做到这一点。
我将不得不调用第一个服务,然后使用类似的东西.iterate
或为每个结果.forEach
调用我的服务getInventoryDetails
我很迷茫。
我没有办法做这样的事情吗?:
compositeDisposable.add(simpleRetrofitService.getAvailableInventories()
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(this::storeNamesToDatabse, this::logErrorAndDisplayPopup)); <-make it blocking and store AvailableInventories somewhere
for (InventoryName inventoryName : availableInventories) {
compositeDisposable.add(simpleRetrofitService.getInventoryDetails()
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(this::storeDetailsToDatabse, this::logErrorAndDisplayPopup)); <-make it blocking and store InventoryDetails somewhere
}
goToNextScreen()
谢谢。
Ps:正如你所看到的 java 8,streams 和 lambda 对我来说是新的
解决方案
在您的情况下,您可以使用flatMap
和zip
运算符,如下所示:
compositeDisposable.add(simpleRetrofitService.getAvailableInventories()
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.doOnSuccess(this::storeNamesToDatabse) // store names on success
.flatMap(this::getInventoryDetails) // once availableInventories is fetched, proceed to get details
.subscribe(inventoryDetailsList -> { // we get a list of inventoryDetails
this.storeDetailsToDatabse(inventoryDetailsList); // modify your function to use list of inventory details instead
goToNextScreen(); // go to next screen when network calls finished
}, this::logErrorAndDisplayPopup))
}
WheregetInventoryDetails(...)
返回另一个Single
向下游发射:
Single<List<InventoryDetails>> getInventoryDetails(AvailableInventories availableInventories) {
List<Single<InventoryDetails>> singles = new ArrayList<>();
for (InventoryName inventoryName : availableInventories) {
singles.add(
simpleRetrofitService.getInventoryDetails(inventoryName)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io()
);
}
return Single.zip(singles, inventoryDetailsList -> (List<InventoryDetails>) inventoryDetailsList); // here you might need to cast the result
}
此外,goToNextScreen()
在订阅回调中移动您的呼叫,以确保在您离开屏幕之前一切都完成(如上所示)。
推荐阅读
- python - 我安装了 python 3.7.4 但我无法安装 dolfin 包
- excel - 为什么相同的代码(Sheets.Add)表现出两种不同的行为?
- web-scraping - 无法从 Flipkart.com 网站抓取图像 src 属性即将变为 emtpy
- javascript - 对象的Javascript数组添加条件值
- javascript - Angular - 错误:无法解析“classlist.js”
- c++ - 如何使用 C/C++ 在 Linux 计算机上查找/刷新本地网络 SAMBA 共享
- javascript - 树数据结构中的高效变更检测/观察器
- javascript - javascript允许我折叠扩展的手风琴
- apache - 如何为不同的域做 RewriteRule
- javascript - 与运行 New React App 相关的问题