Программа выполняется непоследовательно (Kotlin)
Столкнулся с такой проблемой:
В программе есть поля для ввода номера телефона и пароля.
Программа должна подключаться к базе данных Firebase и проверить, есть ли пользователь с таким номером телефона в базе данных и если есть - выполнять код дальше, а если нет - выдавать соответствующий текст.
Но программа идёт дальше независимо от того, есть ли нужные данные в БД, а потом выдаёт текст о том, что этих данных нет.
Код программы:
button_login.setOnClickListener {
var check = true
check = userCheck()
if (check) {
if (!phoneCheck(ed_phone_of_user.text)) {
warning_message_phone.text = "Пожалуйста, введите правильный номер телефона"
warning_message_phone.isVisible = true
check = false
}
if (ed_password.text.length < 6) {
warning_message_password.text = "Пароль должен содержать минимум 6 символов"
warning_message_password.isVisible = true
check = false
}
if (check) {
// Здесь далее выполняется программа
}
}
}
private fun userCheck(): Boolean {
val db = Firebase.firestore
var check = true
val source = Source.SERVER
val phone = convertPhone(ed_phone_of_user.text).trim()
val userRef = db.collection("Users").document(phone)
userRef.get(source)
.addOnSuccessListener { documents ->
if (documents == null) {
warning_message_phone.text = "Такой номер телефона не зарегистрирован"
warning_message_phone.isVisible = true
check = false
} else if (documents["Password"]?.equals(ed_password.text.toString()) == false) {
warning_message_password.text = "Неверный пароль"
warning_message_password.isVisible = true
check = false
}
}
return check
}
То есть он сначала выдаёт сообщение о том, что номер телефона введён неверно, а потом этот текст заменяется текстом о том, что такого номера телефона в базе нет (хотя по задумке, если телефона в БД нет, то дальнейшей проверки быть не должно и выполнение программы прерывается)
Ответы (2 шт):
API Firebase работает в асинхронном режиме используя коллбэк, то есть в момент когда вызывается по референсу .get() создается параллельный поток в котором приложение запрашивает у Firebase данные, при этом приложение не ждет эти данные и идет дальше выполнять код. Когда данные с сервера наконец приходят - автоматически вызывается блок внутри .addOnSuccessListener{}. По этому в момент вызова if (check) данные еще не пришли с сервера и не изменили переменную check, а метод userCheck возвращает первоначальное значение check (true).
Правильным решением будет вынесение проверки номера телефона в отдельный метод, который будет вызываться изнутри .addOnSuccessListener{}, то есть когда данные по факту пришли.
Проблему понял и исправил
Если кто-то столкнулся с такой же проблемой, то объясню как её решил я:
Весь исполняемый код нужно добавить в блок .addOnSuccessListener{}
Вот как у меня вышло:
button_login.setOnClickListener {
if (!phoneCheck(ed_phone_of_user.text)) {
warning_message_phone.text = "Пожалуйста, введите правильный номер телефона"
warning_message_phone.isVisible = true
}
else if (ed_password.text.length < 6) {
warning_message_password.text = "Пароль должен содержать минимум 6 символов"
warning_message_password.isVisible = true
}
else {
val db = Firebase.firestore
val source = Source.SERVER
val userRef = db.collection("Users").document(convertPhone(ed_phone_of_user.text))
userRef.get(source)
.addOnSuccessListener { documents ->
if (!documents.exists()) {
warning_message_phone.text = "Такой номер телефона не зарегистрирован"
warning_message_phone.isVisible = true
} else if (!documents?.get("Password")
?.equals(ed_password.text.toString())!!
) {
warning_message_password.text = "Неверный пароль"
warning_message_password.isVisible = true
} else {
// Тут исполняемый код
}
}
}
}