У меня возникла проблема с реализацией функции анонимного входа в Firebase с сопрограммой Kotlin.
Ниже приведен код для этого:
Repository.kt
suspend fun getUserId(){
firebaseHelper.getUserId().collect{
if (it == "Successful"){
emit(it)
} else {
emit("Task unsuccessful")
}
}
}
FirebaseHelper.kt
fun getUserId() = flow {
val firebaseLoginAsync = Firebase.auth.signInAnonymously().await()
if (firebaseLoginAsync.user != null && !firebaseLoginAsync.user?.uid.isNullOrEmpty()) {
emit("Successful")
} else {
emit("Failed")
}
}
Он отлично работает, когда устройство Android подключено к Интернету.
Но когда я тестирую этот код без интернета, он никогда не завершается, то есть выполнение никогда не достигает if else
блока FirebaseHelper.kt
.
Мне не удалось найти какой-либо ресурс, который помог бы мне понять причину этой проблемы и любое возможное решение.
Одна идея, которую я могу придумать на стороне решения, - принудительно отменить выполнение функций await()
через некоторое время, но я не могу найти ничего, связанного с реализацией.
Он отлично работает, когда устройство Android подключено к Интернету.
Поскольку для операции аутентификации требуется подключение к Интернету, это ожидаемое поведение.
Но когда я тестирую этот код без Интернета, он никогда не завершается.
Без Интернета вы не сможете получить доступ к серверам Firebase, отсюда и такое поведение. Однако, согласно официальной документации функции await():
Эту функцию приостановки можно отменить. Если Job текущей сопрограммы отменяется или завершается, пока эта приостанавливающая функция ожидает, эта функция немедленно возобновляется с CancellationException.
Или вы можете просто проверить, подключен ли пользователь к Интернету перед выполнением аутентификации.
Привет. Помог ли мой ответ? Могу ли я помочь вам с другой информацией?
Я заставил это работать с помощью блока try catch
и функции withTimeout() в файле FirebaseHelper.kt
. Ниже приведен код решения:
fun getUserID() = flow {
try {
val signInTask = Firebase.auth.signInAnonymously()
kotlinx.coroutines.withTimeout(5000) {
signInTask.await()
}
if (signInTask.isSuccessful){
emit("Successful")
} else {
emit("Failed")
}
} catch (e: Exception){
emit("Can't connect to the server\nPlease check your internet connection and retry")
}
}
withTimeout(timeMillis: Long, block: suspend CoroutineScope.() -> T)
запускает данную приостановку block
на timeMillis
миллисекунд и сбрасывает TimeoutCancellationException
, если превышено время ожидания.
В дополнение к моему ответу, поскольку вы используете Kotlin, я думаю, что этот ресурс может помочь.