无法从协程块android中获取数据



存储库实现,其中包含上传和获取url的挂起功能。await()函数说它应该是"suspend"。所以我添加了一个协程范围块。在块中添加了url到列表中。作用域中的日志语句需要在数组列表中下载url。但是在块之外,列表是空的。如何使列表更新以外的协程块,谁能帮助我了解如何与协程工作,谢谢

我的代码
override suspend fun addProductImagesToFirebaseStorage(
productImages: List<Uri>
): AddProductImagesResponse {
return try {
val downloadUrls = mutableListOf<Uri>()
val tasks = mutableListOf<UploadTask>()
productImages.forEach { downloadUrl ->
val task = categoryImageStorage.reference
.child("Home").child("PP")
.child("images")
.putFile(downloadUrl)
tasks.add(task)
}
Tasks.whenAllSuccess<UploadTask.TaskSnapshot>(tasks).addOnSuccessListener { uploadTask ->
uploadTask.forEach {
// downloadUrls.add(it.storage.downloadUrl.await()) Error: Suspension functions can be called only within coroutine body
CoroutineScope(Dispatchers.Default).launch {
downloadUrls.add(it.storage.downloadUrl.await())
Log.i(TAG,"Inside the block : $downloadUrls")
}
Log.i(TAG,"Outside the block : $downloadUrls")
}
}
Success(downloadUrls)
} catch(e:Exception) {
Failure(e)
}
}

这是因为outside日志可能会首先执行,因为将线程更改为Dispatchers.DEFAULT所需的时间比JVM执行下一行所需的时间要多。

我想说的是,coroutine将启动,紧接着,outside日志将打印列表(这是空的),然后协程作业将在另一个线程(Dispatchers.DEFAULT)上完成它的工作,独立于主程序执行流。

我的建议是,使用MutableLiveDataLiveData,这样你就可以观察让主程序在列表被downloadUrl填满时做出反应。

关于LiveData和mutableelivedata的更多信息

正如ndriqa所述,外部日志记录发生在内部日志记录之前,因为您的协程将并行运行,并在日志记录之前等待下载完成。在下载期间,在协程块之外编写的代码继续执行,并且downloadUrls保持空,直到下载完成。因此,您在外部日志中得到空值。

您的目标是确保您的方法addProductImagesToFirebaseStorage在下载完成后返回具有下载值的Success()。由于您的方法是suspend,因此它能够等待一些长操作来完成(在您的示例中是download.await())。但是,您在侦听器的方法中调用await(),因此编译器不知道上下文,也不能确定它是从协程或挂起函数调用的。

就像这样调用它,以确保创建的Success将具有最新的值

val tasks = mutableListOf<UploadTask>()
productImages.forEach { file -> // I renamed downloadUrl to file here to be clearer
val url = categoryImageStorage.reference // I also renamed task to url since the result will be not a task but a downloaded url
.child("Home").child("PP")
.child("images")
.putFile(file)
.await() // wait for it to be put
.storage
.downloadUrl
.await() // wait for it to download
downloadUrls.add(url)
}

最新更新