如何组合多个 API 调用以使用 RxJava 创建单个响应对象

How to combine several API calls to create single response object using RxJava

我正在构建一个包含两个 API 调用的应用程序。我仍在学习 RxJava,我不确定如何正确组合这两个 API 调用

  1. 第一个 API 调用用于检索列表形式的项目
  2. 第二次 API 调用用于使用我从第一次调用获得的项目名称检索项目图像。

我需要显示所有项目及其图像。这些是我使用改造 API 调用

@GET("items/list")
fun getItems(): Observable<ItemResult>

@GET("item/{name}/images")
fun getItemDetails(@Path("name") name: String): Observable<ItemDetails>

这是用RxJava写的代码:

    fun getItemsData(): Observable<ArrayList<ItemDetails>> {

    val data = ArrayList<ItemDetails>()
getItems().flatMap { itemResponse -> Observable.just(itemResponse.message) } //this will give me a list with item names
        .flatMapIterable { data -> data }//iterating over the list and for every item...
        .map { itemName ->//calling to get the item image
            getItemDetails(itemName).map { imageData ->
                val itemImage = imageData.message
                data.add(ItemData(itemName, itemImage))//from this point on I'm lost, I'm not sure if it's the right thing to add here the data
            }.subscribeOn(Schedulers.io())
        }.subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())

    return Observable.create(data)// not sure how to create an Observable from the data
}   

您需要将平面映射流映射到 return 所需的类型 -

getItems()
.flatMap(item -> getItemDetails(item)
                 .map(itemDetail -> ItemData(item, itemDetail.image))
.subscribe(itemData -> // your desired type containing the original item and image);

您没有订阅地图内的内部流。试试这个:

val data = ArrayList<ItemDetails>()
    getItems().flatMap { itemResponse -> Observable.just(itemResponse.message) } //this will give me a list with item names
            .flatMapIterable { data -> data }//iterating over the list and for every item...
            .flatmap(itemName -> getItemDetails(itemName).subscribeOn(Schedulers.io())
            .map(itemDetail -> {//add to the list)})
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())

    return Observable.fromIterable(data);

如果您真的希望 return 一个 Observable<ArrayList<ItemDetails>>,您可以使用 reduce?

类似的东西:

fun getItemsData(): Observable<ArrayList<ItemDetails>> {
   return
     getItems().flatMap { itemResponse -> Observable.just(itemResponse.message) }
               .flatMapIterable { data -> data }
               .flatMap { itemName -> getItemDetails(itemName)  }.subscribeOn(Schedulers.io())
               .map { imageData -> ItemData(itemName, imageData.message) } }
               .reduce(ArrayList<ItemDetails>(), (list, item) -> list.add(item))
               .toObservable()   
               .subscribeOn(Schedulers.io())
               .observeOn(AndroidSchedulers.mainThread())
}

我不确定 Kotlin 中 reduce 的正确语法...

你真的不需要这个...

val data = ArrayList<ItemDetails>()

flatMap 在这里不是正确的运算符:

flatMap { itemResponse -> Observable.just(itemResponse.message) }

您可以使用 map 来简化它(函数 itemResponse -> itemResponse.message 仅对内部值进行操作)。

map { itemResponse -> itemResponse.message }

下一个:

.flatMapIterable { data -> data } // here we have Observable<Message>
.flatMap { itemName ->
     getItemDetails(itemName).map { imageData ->
        ItemData(itemName, imageData)
     }
 } // Observable<ItemData>
.toList() // Single<List<ItemData>> -> you can use toObservable to get an Observable<List<ItemData>>

您可以使用 toList() 而不是手动创建和填充 ArrayList,它简化了事情。