[当需要上一个结果时,如何与RxJava链接几个改造服务?

问题描述 投票:1回答:1

将其用于检索库存的详细信息。我有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(),它将返回一个包含3 AvailableInventoriesInventoryName对象(例如)首先,我想将这些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,流和lambda对我来说是新的

android asynchronous retrofit2 rx-java2
1个回答
0
投票

根据您的情况,可以如下使用flatMapzip运算符:

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))
}

getInventoryDetails(...)返回另一个要向下游发出的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()呼叫以确保在离开屏幕之前一切都完成了(如上所示)。>>

© www.soinside.com 2019 - 2024. All rights reserved.