在我的Android应用上,我正在尝试使用FirebaseAuth实现一个简单的登录/注册。我想使用Kotlin协程来正确处理Firebase的响应。 因此,我将其添加到了我的gradle文件中:
"org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$kotlin_play_services_version"
之后,我能够在FirebaseAuth请求之后调用.await()
。
因此,这是负责处理登录的代码:
override suspend fun signIn(email: String, password: String): JobResult<User> {
var errorMessage = ""
var user: User? = null
firebaseAuth.signInWithEmailAndPassword(email, password)
.addOnSuccessListener { result ->
user = UserMapper().mapFromFirebaseUser(result.user)
}
.addOnFailureListener { result ->
errorMessage = result.message ?: CONSTANTS.BAD_REQUEST
user = null
}.await()
user?.run {
return JobResult.Success(this)
}
return JobResult.Fail(errorMessage, HttpURLConnection.HTTP_BAD_REQUEST)
}
所以基本上发生的是,我正在调用Firebase的Sign In方法传递正确的参数,并添加成功和失败侦听器。根据结果,变量user
可能包含用户的信息或为null。然后根据该变量,将成功或失败的结果返回给请求它的代码部分。
如果结果为肯定(成功侦听器),则一切正常,但是,如果结果不是成功的结果,则.await()
调用之后的代码将永远不会执行!好像它正在等待成功的结果,并将永远等待它。这意味着,如果请求由于某种原因而失败,则暂停功能将永远不会返回任何结果,而只是等待。
我希望其余的代码在收到任何结果后立即运行。我该怎么做?我在这里错过明显的东西吗?
到达故障监听器后,是否有任何方法可以“突破”该await()
并继续执行其余代码?
谢谢!
答案 0 :(得分:1)
您应该这样写。如果您要使用协程,则无需在Task上附加回调侦听器。只需await()任务,然后使用try / catch处理结果:
try {
val result = firebaseAuth.signInWithEmailAndPassword(email, password).await()
val user = UserMapper().mapFromFirebaseUser(result.user)
// continue using user here...
}
catch (e: Exception) {
// deal with the error properly
}
答案 1 :(得分:-1)
override suspend fun signIn(email: String, password: String): JobResult<User> = suspendCancellableCoroutine { cont ->
var errorMessage = ""
var user: User? = null
firebaseAuth.signInWithEmailAndPassword(email, password)
.addOnSuccessListener { result ->
user = UserMapper().mapFromFirebaseUser(result.user)
if(cont.isActive){
cont.resume(JobResult.Success(this))
}
}
.addOnFailureListener { result ->
errorMessage = result.message ?: CONSTANTS.BAD_REQUEST
user = null
if(cont.isActive){
cont.resume(JobResult.Fail(errorMessage, HttpURLConnection.HTTP_BAD_REQUEST))
}
}
}