Как правильно обработать FirebaseAuth asyn c результаты? - PullRequest
0 голосов
/ 13 февраля 2020

В моем приложении Android я пытаюсь реализовать простой вход в систему / регистрацию с использованием FirebaseAuth. Я хотел использовать Kotlin сопрограммы для правильной обработки ответов от Firebase. Поэтому я добавил это в свой файл Gradle:

"org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$kotlin_play_services_version"

После этого я смог вызвать .await() после запроса FirebaseAuth. Итак, вот код, который отвечает за обработку входа в систему:

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, передавая правильные параметры и добавляя прослушиватель Success и Failure Listener. В зависимости от результата, переменная user может содержать информацию о пользователе или быть нулевой. И в зависимости от этой переменной я возвращаю результат Success или Failure той части кода, которая его запросила.

Все работает хорошо, если результат положительный (Success Listener), однако, если результат что-либо кроме успешного результата, код после вызова .await() никогда не выполняется! Как будто он ждет успешного результата и будет ждать его вечно. Это означает, что если запрос по какой-то причине завершается неудачно, то функция приостановки никогда не будет возвращать никаких результатов, она просто ждет.

Я хочу, чтобы остальная часть кода выполнялась, как только ЛЮБОЙ результат получен. Как мне это сделать? Я что-то упускаю здесь очевидное? Есть ли какой-нибудь способ «вырваться» из этого await() и продолжить работу с остальным кодом, когда будет достигнут прослушиватель ошибок?

Спасибо!

Ответы [ 2 ]

1 голос
/ 13 февраля 2020

Вы должны написать это так. Если вы собираетесь использовать сопрограммы, нет необходимости присоединять слушателей обратного вызова к Задаче. Просто подождите () задачу и используйте 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
}
0 голосов
/ 13 февраля 2020
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))
        }
    }
}
...