存储库实现,其中挂起上传和取回urls的功能。等待()函数说它应该是“暂停”。所以我添加了一个Coroutine范围块。在该块中,已将urls添加到列表中。作用域中的log语句要求在arraylist中下载urls。但是在块之外,列表是空的。如何在coroutine块之外更新列表,谁能帮助我理解如何使用Coroutine (谢谢)?
我的代码
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)
}
}
发布于 2022-11-23 09:10:20
这是因为可能会首先执行outside
日志,因为将线程更改为Dispatchers.DEFAULT
所花费的时间比执行下一行所花费的时间要多。
我想说的是,coroutine
将启动,在此之后,outside
日志将立即打印列表(该列表为空),然后协同工作将在另一个线程(Dispatchers.DEFAULT
)上完成,这与主程序执行流程无关。
我的建议是使用MutableLiveData
或LiveData
,这样您就可以观察,让主程序在列表中装满downloadUrl时做出反应。
以下是关于LiveData和MutableLiveData的更多信息
发布于 2022-11-23 10:50:54
正如ndriqa所述,外部日志记录发生在内部日志记录之前,因为您的协同机制将并行运行,并等待下载完成后再登录。在下载期间,您在coroutine块之外编写的代码继续执行,在下载完成之前,您的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)
}
https://stackoverflow.com/questions/74543613
复制相似问题