Как объединить несколько сервисов модернизации с Rx Java, когда мне нужны результаты предыдущего? - PullRequest
1 голос
/ 10 марта 2020

.

ученик, чтобы получить детали инвентаризации, чтобы сделать. У меня есть 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

Наконец мне нужно перенаправить на другой экран.

Как можно Я делаю это в Rx Java? Раньше я бы использовал простые android асинхронные задачи и сделал их не асинхронными, используя .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, потоки и лямбда для меня новы

1 Ответ

0 голосов
/ 10 марта 2020

В вашем случае вы можете использовать операторы 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))
}

Где 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() в обратный вызов подписки, чтобы убедиться, что все завершается до того, как вы покинете экран (как показано выше).

...