将Firebase与Kotlin协程一起使用

时间:2019-08-19 19:29:43

标签: android firebase kotlin kotlin-coroutines

我在我的应用程序中使用Kotlin协程,并且选择了Firebase作为数据库和存储的选择。 探索了Firebase之后,我意识到它的所有API都是异步的,并且异步调用的结果都在回调中返回,而摆脱回调是我在应用中使用Kotlin协程的主要原因。

这是我编写的用于将文件上传到Firebase云存储的代码,但它给出了“任务尚未完成”错误。

private suspend fun saveImage(filePath: String): String? {
        val storage = FirebaseStorage.getInstance("gs://myapp-9a648.appspot.com/")
        val storageRef = storage.reference
        val file = Uri.fromFile(File(filePath))
        val imageRef = storageRef.child("images/${file.lastPathSegment}")
        return withContext(Dispatchers.IO) {
            imageRef.putFile(file).snapshot.storage.downloadUrl.result.toString()
        }
    }
  

E / Android运行时:致命异常:主要       程序:pk.com.kotlinapp,PID:7491       java.lang.IllegalStateException:任务尚未完成           在com.google.android.gms.common.internal.Preconditions.checkState(未知   资源)           在com.google.android.gms.tasks.zzu.zzb(未知来源)           在com.google.android.gms.tasks.zzu.getResult(未知来源)           在prk.com.kotlinapptest.DatabaseManager $ saveImage $ 2.invokeSuspend(DatabaseManager.kt:28)           在kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)           在kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)           在kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)           在kotlinx.coroutines.scheduling.CoroutineScheduler.access $ runSafely(CoroutineScheduler.kt:60)           在kotlinx.coroutines.scheduling.CoroutineScheduler $ Worker.run(CoroutineScheduler.kt:740)

有什么方法可以将文件上传到Firebase云存储并获取下载URL,而无需在其成功回调中获取下载URL?

1 个答案:

答案 0 :(得分:2)

kotlinx-coroutines-play-services library提供了await扩展功能,可以等待任务完成,例如:

...
dependencies {
  ...
  implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.3.1"
}
return withContext(Dispatchers.IO) {
    imageRef
        .putFile(file)
        .await() // await() instead of snapshot
        .storage
        .downloadUrl
        .await() // await the url
        .toString()
}