问题
I am using Kotlin coroutines in my app and have chosen firebase as my choice for database and storage. After exploring firebase I realized that all its APIs are asynchronous and the result of the asynchronous calls are returned in a callback, and getting rid of callbacks is the main reason why I am using Kotlin coroutines in my app.
This is the code I have written to upload a file to firebase cloud storage but it is giving "Task is not yet complete" error.
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/AndroidRuntime: FATAL EXCEPTION: main Process: pk.com.kotlinapp, PID: 7491 java.lang.IllegalStateException: Task is not yet complete at com.google.android.gms.common.internal.Preconditions.checkState(Unknown Source) at com.google.android.gms.tasks.zzu.zzb(Unknown Source) at com.google.android.gms.tasks.zzu.getResult(Unknown Source) at prk.com.kotlinapptest.DatabaseManager$saveImage$2.invokeSuspend(DatabaseManager.kt:28) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241) at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594) at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)
Is there any way I can upload a file to firebase cloud storage and get back the download URL without getting the download URL in its success callback?
回答1:
kotlinx-coroutines-play-services
library provides await extension function that allows to await the task completion, like:
...
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()
}
来源:https://stackoverflow.com/questions/57562864/using-firebase-with-kotlin-coroutines