如何将 Android Task 转换为 Kotlin Deferred?
How to transform an Android Task to a Kotlin Deferred?
Firebase 匿名登录 returns task (which is basically Google promise implementation):
val task:Task<AuthResult> = FirebaseAuth.getInstance().signInAnonymously()
如何创建一个 signInAnonymous
包装器,其中:
是suspend
函数,等待task
完成
suspend fun signInAnonymous(): Unit
它returns一个Deferred
对象,异步传递结果
fun signInAnonymous() : Deferred
基于this GitHub library, here's a way to transform a Task
into a suspending function in the "usual" way以适应基于回调的异步调用协程:
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"))
}
}
}
当然也可以用Deferred
包起来,CompletableDeferred
这里就派上用场了:
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
}
要将其转换为协程就绪函数,我会使用任务 API:
中的 Tasks.await()
函数
suspend fun FirebaseAuth.signInAnonymouslyAwait(): AuthResult {
return Tasks.await(this.signInAnonymously())
}
至于延迟,我会坚持 zsmb13 的回答
软件包 kotlinx.coroutines.tasks
现在包含以下实用函数:
public suspend fun <T> Task<T>.await(): T { ... }
来自docs:
Awaits for completion of the task without blocking a thread.
This suspending function is cancellable.
If the Job of the current coroutine is cancelled or completed while this suspending function is waiting, this function stops waiting for the completion stage and immediately resumes with CancellationException.
public fun <T> Task<T>.asDeferred(): Deferred<T> { ... }
来自docs:
Converts this task to an instance of Deferred.
If task is cancelled then resulting deferred will be cancelled as well.
所以你可以这样做:
suspend fun signInAnonymouslyAwait(): AuthResult {
return FirebaseAuth.getInstance().signInAnonymously().await()
}
或:
fun signInAnonymouslyDeferred(): Deferred<AuthResult> {
return FirebaseAuth.getInstance().signInAnonymously().asDeferred()
}
将此添加到 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()
}
Firebase 匿名登录 returns task (which is basically Google promise implementation):
val task:Task<AuthResult> = FirebaseAuth.getInstance().signInAnonymously()
如何创建一个 signInAnonymous
包装器,其中:
是
suspend
函数,等待task
完成suspend fun signInAnonymous(): Unit
它returns一个
Deferred
对象,异步传递结果fun signInAnonymous() : Deferred
基于this GitHub library, here's a way to transform a Task
into a suspending function in the "usual" way以适应基于回调的异步调用协程:
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"))
}
}
}
当然也可以用Deferred
包起来,CompletableDeferred
这里就派上用场了:
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
}
要将其转换为协程就绪函数,我会使用任务 API:
中的Tasks.await()
函数
suspend fun FirebaseAuth.signInAnonymouslyAwait(): AuthResult {
return Tasks.await(this.signInAnonymously())
}
至于延迟,我会坚持 zsmb13 的回答
软件包 kotlinx.coroutines.tasks
现在包含以下实用函数:
public suspend fun <T> Task<T>.await(): T { ... }
来自docs:
Awaits for completion of the task without blocking a thread.
This suspending function is cancellable.
If the Job of the current coroutine is cancelled or completed while this suspending function is waiting, this function stops waiting for the completion stage and immediately resumes with CancellationException.
public fun <T> Task<T>.asDeferred(): Deferred<T> { ... }
来自docs:
Converts this task to an instance of Deferred.
If task is cancelled then resulting deferred will be cancelled as well.
所以你可以这样做:
suspend fun signInAnonymouslyAwait(): AuthResult {
return FirebaseAuth.getInstance().signInAnonymously().await()
}
或:
fun signInAnonymouslyDeferred(): Deferred<AuthResult> {
return FirebaseAuth.getInstance().signInAnonymously().asDeferred()
}
将此添加到 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()
}