Kotlin中如何串行调用带回调的uploadVideo方法?
问题
我有一个从服务器返回响应的uploadVideo方法,定义如下:
fun uploadVideo(link: String, completionHandler: (Result<String>) -> Unit) { // some action completionHandler(Result.success("")) }
我希望逐个调用该方法,必须等待前一个请求的响应返回后,再调用下一个,示例场景如下:
uploadVideo("https://stackoverflow.com/video1.mp4") { } // 仅在前一个请求响应返回后再调用 uploadVideo("https://stackoverflow.com/video2.mp4") { } // 仅在前一个请求响应返回后再调用 uploadVideo("https://stackoverflow.com/video3.mp4") { }
我尝试用suspendCancellableCoroutine将其封装为挂起函数:
suspend fun uploadVideo(link: String?): String? = suspendCancellableCoroutine { cont -> uri?.let { uploadVideo(link, completionHandler = { it.onSuccess { uri -> cont.resume(uri.toString()) }.onFailure { cont.resumeWithException(it) } } ) } ?: kotlin.run { cont.resume(null) } }
并按如下方式调用:
uploadVideo("https://stackoverflow.com/video1.mp4") uploadVideo("https://stackoverflow.com/video2.mp4") uploadVideo("https://stackoverflow.com/video3.mp4")
但这些方法并未串行执行,而是并行执行了,请问该如何解决?
解决方案
你的挂起函数封装逻辑没问题,但调用方式有误——挂起函数本身不会自动保证串行,必须在同一个协程内按顺序调用,利用挂起函数会暂停协程的特性,等待前一个请求完成后再执行下一行代码。
步骤1:修正挂起函数封装(修复变量未定义问题)
原封装代码里的uri是未定义变量,调整为正确的版本:
suspend fun uploadVideoSuspend(link: String): String = suspendCancellableCoroutine { cont -> uploadVideo(link) { result -> result.onSuccess { cont.resume(it) } .onFailure { cont.resumeWithException(it) } } }
如果需要支持link为null的场景,可保留返回String?的逻辑,确保变量引用正确即可。
步骤2:在协程内顺序调用
将所有上传调用放在同一个协程作用域(比如viewModelScope、LifecycleScope)内,按顺序编写代码,挂起函数会自动暂停协程,直到当前请求完成后再执行下一个:
// 在协程作用域内执行 viewModelScope.launch { try { // 第一个上传完成后才会执行第二个 val result1 = uploadVideoSuspend("https://stackoverflow.com/video1.mp4") // 第二个上传完成后才会执行第三个 val result2 = uploadVideoSuspend("https://stackoverflow.com/video2.mp4") val result3 = uploadVideoSuspend("https://stackoverflow.com/video3.mp4") // 所有上传完成后的处理逻辑 } catch (e: Exception) { // 处理上传失败的异常 } }
步骤3:批量处理视频链接(可选)
如果有多个视频链接需要串行上传,用循环遍历更简洁:
viewModelScope.launch { val videoLinks = listOf( "https://stackoverflow.com/video1.mp4", "https://stackoverflow.com/video2.mp4", "https://stackoverflow.com/video3.mp4" ) for (link in videoLinks) { try { val result = uploadVideoSuspend(link) // 单个视频上传成功的处理逻辑 } catch (e: Exception) { // 可选:失败后中断后续上传,或继续执行 break // 中断后续上传 // continue // 忽略当前失败,继续上传下一个 } } }
为什么之前的调用会并行?
如果你的三次uploadVideo调用是在不同协程中执行(比如分别用launch启动),就会导致并行。只要确保所有调用都在同一个协程的代码块内,按顺序编写,就能保证串行执行。
内容的提问来源于stack exchange,提问作者wprpovhtguetbfdotm
相关产品推荐
相关产品推荐

