kotlin runBlocking协程中的两个方法,第二个不等待第一个

laik7k3q  于 6个月前  发布在  Kotlin
关注(0)|答案(2)|浏览(76)

我遇到的问题是我的saveStore函数没有等待uploadImagesFunction函数。最后一个函数循环通过一个包含多个图像的数组,并将每个图像加载到Firebase Storage中。saveStore函数应该只在所有图像都处理完后才被调用。为此,我使用runBlocking协程。问题是saveStore总是立即被调用而不等待第一个方法完成。我必须改变什么?

binding.save.setOnClickListener {

 runBlocking(Dispatchers.IO) {
   uploadImagesFunction()
   saveStore()

  }

}

...

 private fun uploadImagesFunction(){

    val storeImageRef = storageRef.child("/storeImages/${UUID.randomUUID()}.jpg")

     uploadImages.forEach { element ->
        var file = element
        val uploadTask = storeImageRef.putFile(file)
        uploadTask.addOnFailureListener {
         //Error
           ...
        }.addOnSuccessListener { taskSnapshot ->
          //Success - go on
         
        }

    }
}

private fun saveStore(){

    val store = hashMapOf(
        "name" to  binding.storeName.editableText.toString(),
        ...
    )

    db.collection("stores").add(store).addOnSuccessListener {document->

    ... }

   }

字符串

ycggw6v2

ycggw6v21#

这里没有使用suspend函数,所以没有真正使用协程。您的函数是使用另一种异步机制(基于回调)的常规函数。
如果你真的想使用协程,你应该让这些协程调用挂起,而不是使用回调。
如果您使用的是Firebase,您可能可以利用kotlinx-coroutines-play-services库,并为此使用Task.await()Task.asDeferred()函数,而不是使用addOnSuccessListener等。
例如:

import kotlinx.coroutines.tasks.asDeferred
import kotlinx.coroutines.tasks.await

binding.save.setOnClickListener {
    lifecycleScope.launch {
        uploadImagesFunction()
        saveStore()
    }
}

private suspend fun uploadImagesFunction() {
    val storeImageRef = storageRef.child("/storeImages/${UUID.randomUUID()}.jpg")
    uploadImages
        .map { file -> storeImageRef.putFile(file).asDeferred() } 
        .awaitAll()
}

private suspend fun saveStore() {
    val store = hashMapOf(
        "name" to  binding.storeName.editableText.toString(),
        ...
    )

    db.collection("stores").add(store).await()
}

字符串
请注意,您在这里为每个图像分配了相同的UUID,这可能不是您想要的。您可能应该为列表中的每个项目生成一个新的UUID(只需将storageRed.child(...)调用移动到map中)。

ss2ws0br

ss2ws0br2#

不推荐使用runBlocking,因为它会导致UI无响应。您应该使用协程来利用异步编程。

lifecycleScope.launch(Dispatchers.IO) {
            uploadImagesFunction(
                onComplete = {
                    saveStore()
                }
            )
        }

private suspend fun uploadImagesFunction(onComplete: () -> Unit) {
    val storeImageRef = storageRef.child("/storeImages/${UUID.randomUUID()}.jpg")
    uploadImages.forEach { element ->
        var file = element
        storeImageRef.putFile(file).await()
    }
    onComplete()
}

字符串

相关问题