如何正确调用依赖于另一个 API Kotlin 响应的 API

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

我有一个API“breedImageByID(referenceImageId:String)”,它依赖于“getBreeds()”API来获取referenceImageId。获取数据后,我需要使用 getBreeds 数据和 BreedImageByID() 数据填充列表中的每个项目。但执行此操作后,它的行为很奇怪,breedImageByID() 图像无法与 getBreed() 数据正确对齐以填充列表中的每个项目。我该如何解决这个问题。

品种筛选:

@Composable
fun BreedListItem(
    breed: BreedItem,
    catImage: CatImage,
    viewModel: BreedSharedViewModel,
    navController: NavController
) {

    val breedImageURL = remember {
        breed.reference_image_id.let { imageId ->
            viewModel.breedImageByID.value.data?.url ?: ""
        }
    }

    Row(
        modifier = Modifier
            .fillMaxSize()
            .padding(6.dp)
            .clip(RoundedCornerShape(18.dp))
            .background(Color.Gray)
            .clickable {
                viewModel.addBreedItem(breed)
                navController.navigate(DetailsNavScreen.BreedsDetail.route)
            },
        verticalAlignment = Alignment.CenterVertically
    ) {

        Row(
            modifier = Modifier
                .width(120.dp)
                .height(80.dp)
                .clip(RoundedCornerShape(12.dp))
        ) {
            SubcomposeAsyncImage(
                model = breedImageURL,
                contentDescription = null,
                contentScale = ContentScale.FillBounds
            )
        }

        Text(
            text = breed.name,
            modifier = Modifier.padding(start = 15.dp),
            fontWeight = FontWeight.ExtraBold,
            fontSize = 17.sp
        )
    }
    Spacer(modifier = Modifier.height(10.dp))
}

BreedSharedViewModel:

val breeds: MutableState<NetworkResult<GetBreeds>> =
    mutableStateOf(NetworkResult.Loading())

val breedImageByID: MutableState<NetworkResult<CatImage>> =
    mutableStateOf(NetworkResult.Loading())


private fun getBreeds() = viewModelScope.launch {

    repository.getBreeds().collect { values ->
        breeds.value = values

        values.data?.forEach {
            it.reference_image_id?.let { imageId ->
                breedImageByID(imageId)
                breedImageByID.value.data?.let {
                    it1 ->
                    Log.i("catImageID", it1.url)
                }
            }
        }
    }
}

fun breedImageByID(referenceImageId: String) = viewModelScope.launch {
    repository.getCatImageByID(referenceImageId).collect { values ->
        breedImageByID.value = values
    }
}

android kotlin android-jetpack-compose retrofit kotlin-coroutines
1个回答
0
投票

launch
async
是 kotlin 中可用的协程构建器。
launch
函数遵循
fire and forget
方法,这本质上意味着它将启动一个协程并忘记其结果。而
aync
返回
Deferred
的实例,它具有名为
await
的函数,可用于等待结果。在协程构建器中,您可以创建多个不一定同步的协程。您在这里尝试做的事情也是一样的。当您调用
breedImageByID
时,您启动了另一个协程,它不会等待其结果。要使其同步,请尝试如下
await

suspend fun breedImageByID(referenceImageId: String) = viewModelScope.async {
    repository.getCatImageByID(referenceImageId)
}.await()

请注意,我在函数定义之前添加了

suspend
关键字。另请确保
getCatImageByID
suspend
函数。上面的代码对每个猫图像 ID 进行网络调用以进行繁殖。

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