Kotlin Coroutine改造-连锁网络通话

时间:2019-09-14 23:46:40

标签: android kotlin kotlin-coroutines

我正在尝试使用Kotlin Coroutines + Retrofit进行网络呼叫,但是当前的实现存在两个问题。

A)仅在我的循环完成后返回。

B)似乎要等待循环中的每个呼叫完成,然后再进行下一个呼叫。

我正在与之交互的API要求我进行初始提取,返回itemId的数组

[ 1234, 3456, 3456 ... ]

,对于上述响应中的每个项目,请获取具有ID的项目

{ id: 1234, "name": "banana" ... }

我当前的实现如下,我在做什么错了?

suspend operator fun invoke(feedType: String): NetworkResult<List<MyItem>> = withContext(Dispatchers.IO) {
    val itemList: MutableList< MyItem > = mutableListOf()
    val result = repository.fetchItems()
    when (result) {
        is NetworkResult.Success -> {
            itemList.addAll(result.data)
            for (i in itemList) {
                val emptyItem = result.data[i]
                val response = repository.fetchItem(emptyItem.id)

                when (response) {
                    is NetworkResult.Success -> {
                        val item = response.data
                        emptyItem.setProperties(item)
                    }
                }
            }
        }
        is NetworkResult.Error -> return@withContext result
    }
    return@withContext NetworkResult.Success(itemList)
}

1 个答案:

答案 0 :(得分:1)

我建议您使用async分别处理每个项目:

suspend operator fun invoke(feedType: String): NetworkResult<List<MyItem>> = withContext(Dispatchers.IO) {
    when (val result = repository.fetchItems()) { // 1
        is NetworkResult.Success -> {
            result.data
                .map { async { fetchItemData(it) } } // 2
                .awaitAll() // 3
            NetworkResult.Success(result.data)
        }
        is NetworkResult.Error -> result
    }
}

private suspend fun fetchItemData(item: MyItem) {
    val response = repository.fetchItem(item.id)
    if (response is NetworkResult.Success) {
        item.setProperties(response.data)
    }
}

在此代码中,首先,我们调用fetchItems以获取商品ID(1)。然后,我们同时为每个项目调用fetchItem(2)。使用协程和async可以轻松完成此操作。然后,我们等待所有数据都将被提取(3)。