首页 > 解决方案 > 同步多个 api 调用 Android RxJava

问题描述

我有 2 个 API 调用:

我需要我们调用的产品列表,一旦我有了它,从第二个 api 调用中一一调用额外的信息。一旦我拥有了所有,我必须对所有数据进行 mnix 以获得“CompleteInfoProduct”列表

我能够获取Call1的信息,我终于实现了获取更多信息产品(call2)的列表。这就是问题所在,我不知道如何将 call2 与 call1 的项目“匹配”。

简化示例:

getProducts()
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe { response ->
            if (response.success) {
                val productsId = response.products.map { it.id }

                val obversableListMoreInfoProducts = mutableListOf<Observable<MoreInfoProductResponse>>()

                productsId.forEach { productId ->
                    obversableListMoreInfoProducts.add(
                            this.model.getMoreInfoProduct(productId)
                    )
                }

                val sub = Observable.merge(obversableListMoreInfoProducts)
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .toList()
                        .subscribe { it ->
                            Logger.d("Size MoreInfoProducts: ${it.size}")
                            <HERE I HAVE THE LIST OF MORE INFO . THE PROBLEM IS THAT THIS MODDEL DONT HAVE THE ID OF THE PRODUCT, AND I DON'T KNWO HOW TO JOIN WITH IT>
                        }
                addSubscription(sub)
            }
        }

如何同步和混合所有信息?

标签: androidrestrx-java2rx-android

解决方案


最简单的解决方案可能与此类似:

class SO64424129 {
    private fun getProducts(): Single<List<Int>> { // (1)
        return Single.just(listOf(1, 2, 3, 4)).delay(1, TimeUnit.SECONDS)
    }

    private fun getProductInfo(productId: Int): Single<String> { // (2)
        return Single.just("PI: $productId")
            .delay(Random().nextLong().rem(1000), TimeUnit.MILLISECONDS)
    }

    fun getFullProducts(): Single<List<String>> {
        return getProducts()
            .flatMap { ids ->
                Observable.fromIterable(ids) // (3)
                    .flatMapSingle { productId ->
                        getProductInfo(productId)
                            .map {  productInfo -> "$productId $productInfo" } // (4)
                    }
                    .toList() // (5)
            }
    }
}

class SO64424129Test {

    @Test
    fun `when full products required then list of full products received`() {
        val tested = SO64424129()

        val testSubscription = tested.getFullProducts().test()

        testSubscription.await()
        testSubscription.assertValue { listOfProducts ->
            listOfProducts.containsAll(listOf("1 PI: 1", "2 PI: 2", "3 PI: 3", "4 PI: 4"))
        }
        testSubscription.assertNoErrors()
    }
}

有趣的部分:

  1. getProducts()返回一个“产品 ID”列表,并有一些延迟以模仿真实的 API
  2. getProductInfo()返回单个产品信息。为了简单起见,我只是将给定的 ID 转换为 String "PI: $productId",但你可以做任何你想做的事情。
  3. 创建Observable将给定 id 列表作为单个项目(一项一项)发出的内容。
  4. 结合 id ( Product) 和产品信息字符串表示 ( InfoProduct )
  5. toList()等待Complete事件,组合所有发出ProductInfo的 's,并将它们作为单个列表发出。

推荐阅读