简体   繁体   中英

Kotlin coroutine with firebase functions

I was having a problem implementing the Firebase anonymous sign-in function with Kotlin coroutine.

Following is the code for that:

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")
   }
}

It works fine when the android device is connected to the inte.net.
But when I test this code without the inte.net it never completes, that is, the execution never reaches the if else block of FirebaseHelper.kt .

I was unable to find any resource that would help me understand the cause of this problem and any possible solution.
One idea that I can think of on the solution side is to forcefully cancel the await() functions execution after some time but I can't find anything related to implementation.

It works fine when the android device is connected to the inte.net.

Since an authentication operation requires an inte.net connection, then that's the expected behavior.

But when I test this code without the inte.net it never completes.

Without the inte.net, there is no way you can reach Firebase servers, hence that behavior. However, according to the official documentation of await() function:

This suspending function is cancellable. If the Job of the current coroutine is canceled or completed while this suspending function is waiting, this function immediately resumes with CancellationException.

Or you can simply check if the user is connected to the inte.net before performing the authentication.

The way that I made it work is with help of try catch block and withTimeout() function in FirebaseHelper.kt file. Following is the code of solution:

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) runs the given suspend block for timeMillis milliseconds and throws TimeoutCancellationException if the timeout was exceeded.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM