19

Firebase 匿名登录返回一个任务(基本上是Google 承诺实现):

val task:Task<AuthResult> = FirebaseAuth.getInstance().signInAnonymously()

如何创建一个signInAnonymous包装器,其中:

  • 是一个suspend函数,等待task完成

    • suspend fun signInAnonymous(): Unit
  • 它返回一个Deferred对象,异步传递结果

    • fun signInAnonymous() : Deferred
4

4 回答 4

18

该软件包kotlinx.coroutines.tasks现在包括以下实用功能:

public suspend fun <T> Task<T>.await(): T { ... }

文档

等待任务完成而不阻塞线程。
这个暂停功能是可以取消的。
如果当前协程的Job在此挂起函数等待期间被取消或完成,则此函数将停止等待完成阶段并立即以CancellationException恢复。

public fun <T> Task<T>.asDeferred(): Deferred<T> { ... }

文档

将此任务转换为Deferred的实例。
如果任务被取消,那么导致的延迟也将被取消。


所以你可以这样做:

suspend fun signInAnonymouslyAwait(): AuthResult {
    return FirebaseAuth.getInstance().signInAnonymously().await()
}

或者:

fun signInAnonymouslyDeferred(): Deferred<AuthResult> {
    return FirebaseAuth.getInstance().signInAnonymously().asDeferred()
}
于 2019-11-03T09:32:17.847 回答
11

基于这个 GitHub 库,这是一种以“通常”的方式Task将 a转换为挂起函数的方法,以适应基于回调的异步调用协程:

suspend fun <T> Task<T>.await(): T = suspendCoroutine { continuation ->
    addOnCompleteListener { task ->
        if (task.isSuccessful) {
            continuation.resume(task.result)
        } else {
            continuation.resumeWithException(task.exception ?: RuntimeException("Unknown task exception"))
        }
    }
}

当然你也可以把它包起来,DeferredCompletableDeferred这里就派上用场了:

fun <T> Task<T>.asDeferred(): Deferred<T> {
    val deferred = CompletableDeferred<T>()

    deferred.invokeOnCompletion {
        if (deferred.isCancelled) {
            // optional, handle coroutine cancellation however you'd like here
        }
    }

    this.addOnSuccessListener { result -> deferred.complete(result) }
    this.addOnFailureListener { exception -> deferred.completeExceptionally(exception) }

    return deferred
}
于 2018-05-22T17:52:26.020 回答
4

将此添加到gradle

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.4.3'

然后你可以像这样使用它:

suspend fun login(email: String, pass: String) {
    FirebaseAuth.getInstance().signInWithEmailAndPassword(email, pass).await()
}
于 2021-03-09T11:26:11.203 回答
3

要将其转换为可用于协程的函数,我将使用Tasks.await()Tasks API 中的函数:

suspend fun FirebaseAuth.signInAnonymouslyAwait(): AuthResult {
    return Tasks.await(this.signInAnonymously())
}

至于延期,我会坚持 zsmb13 的回答

于 2018-05-29T22:13:42.723 回答