我如何合并一个返回一个数组的调用,并对该数组的每个元素进行多次调用?

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

很抱歉,该标题不够清楚,但我不知道如何用一句话来总结。

我有一个Web服务,该服务返回一个名为Father的对象的ArrayList。

父亲对象的结构如下:

class Father {
   ArrayList<Child> children;
}

我还有另一个Web服务,可以向我返回对象Child的详细信息。

如何合并第一个返回Father的数组列表和多个对象Child的多个调用的调用?

到目前为止,我可以像这样单独拨打电话:

要求父亲的ArrayList

myRepository.getFathers().subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io()).subscribeWith(new DisposableSingleObserver<List<Father>>() {

})

多次调用子级ArrayList

childListObservable
  .subscribeOn(Schedulers.io())
  .observeOn(Schedulers.io())
  .flatMap((Function<List<Child>, ObservableSource<Child>>) Observable::fromIterable)
  .flatMap((Function<Child, ObservableSource<Child>>) this::getChildDetailObservable)
  .subscribeWith(new DisposableObserver<Child>() {

// do whatever action after the result of each Child

}))
retrofit rx-java
1个回答
0
投票

先决条件

等级

implementation("io.reactivex.rxjava2:rxjava:2.2.10")

testImplementation("io.mockk:mockk:1.10.0")

testImplementation("org.assertj:assertj-core:3.11.1")

testImplementation("org.junit.jupiter:junit-jupiter-api:5.3.1")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.3.1")

类/接口

interface Api {
    fun getFather(): Single<List<Father>>

    fun childDetailInfo(child: Child): Single<ChildDetailInfo>
}

interface Store {
    fun store(father: Father): Completable

    fun store(child: ChildDetailInfo): Completable
}

class ApiImpl : Api {
    override fun getFather(): Single<List<Father>> {
        val child = Child("1")
        val child1 = Child("2")
        return Single.just(listOf(Father(listOf(child, child1)), Father(listOf(child))))
    }

    override fun childDetailInfo(child: Child): Single<ChildDetailInfo> {
        return Single.just(ChildDetailInfo(child.name))
    }
}

data class Father(val childes: List<Child>)

data class Child(val name: String)

data class ChildDetailInfo(val name: String)

解决方案

    val fathersStore = api.getFather()
            .flatMapObservable {
                Observable.fromIterable(it)
            }.flatMapCompletable {
                val detailInfos = it.childes.map { child ->
                    api.childDetailInfo(child)
                            .flatMapCompletable { detail -> store.store(detail) }
                }

                store.store(it)
                        .andThen(Completable.concat(detailInfos))
            }

在每次列出父亲列表时,该列表都是平坦的。下一位操作者(flatMapCompletable)将担任父亲。该完成项将使用Api#childDetailInfo获取每个Child的详细信息。结果是通过一一调用API来构建的。没有并发事件发生在wegen“ concat”。成功存储父亲后,成功检索后,孩子也将被存储。如果其中一个API调用失败(例如,网络),则所有操作都会失败,因为onError将传播给订阅者。

测试

@Test
fun so62299778() {
    val api = ApiImpl()
    val store = mockk<Store>()

    every { store.store(any<Father>()) } returns Completable.complete()
    every { store.store(any<ChildDetailInfo>()) } returns Completable.complete()

    val fathersStore = api.getFather()
            .flatMapObservable {
                Observable.fromIterable(it)
            }.flatMapCompletable {
                val detailInfos = it.childes.map { child ->
                    api.childDetailInfo(child)
                            .flatMapCompletable { detail -> store.store(detail) }
                }

                store.store(it)
                        .andThen(Completable.concat(detailInfos))
            }

    fathersStore.test()
            .assertComplete()

    verify { store.store(eq(Father(listOf(Child("1"), Child("2"))))) }
    verify { store.store(eq(Father(listOf(Child("1"))))) }

    verify(atLeast = 2) { store.store(eq(ChildDetailInfo("1"))) }
    verify(atLeast = 1) { store.store(eq(ChildDetailInfo("2"))) }
}

下一次请提供一些类/接口。当您的问题包含所有重要信息时,您会更快得到答案。

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