Search code examples
androidkotlinandroid-jetpack-composekotlin-coroutines

How to Prevent CircularProgressIndicator from freezing during Authentication in Kotlin Compose?


I have a Kotlin Compose app that allows users to authenticate with Facebook and Google. During the login process, a CircularProgressIndicator is displayed and spins until the user's account creation and login are completed. However, the CircularProgressIndicator freezes for a few seconds, it looks like the app is blocked. I suspect this is due to thread management issues, as the login process runs on a separate thread.

Does anyone have suggestions on how to keep the CircularProgressIndicator running smoothly without any interruptions? Should I consider placing it on a dedicated thread?

This how I do the google login:

@Composable
fun activityGoogleResultLauncher(): ActivityResultLauncher<Intent> {
    val loginViewModel = LocalUserState.current
    val startAutocomplete: ActivityResultLauncher<Intent> = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.StartActivityForResult()
    ) { result ->
        val completedTask: Task<GoogleSignInAccount> =
            GoogleSignIn.getSignedInAccountFromIntent(result.data)
        try {
            if (completedTask.isSuccessful) {
                val account: GoogleSignInAccount? =
                    completedTask.getResult(ApiException::class.java)
                val email = account?.email
                val token: String = account?.idToken!!
                runBlocking {
                    loginViewModel.singInWithGoogle(token)
                    loginViewModel.getUserType = true
                    loginViewModel.loginStatus = "in"
                    FirebaseMessaging.getInstance().token.addOnCompleteListener {
                        loginViewModel.insertFCMWhenLogin(it.result)
                    }
                    if (email != null) {
                        loginViewModel.updateEmail(email)
                    }
                }
            } else {
                println("AUTH Google Auth failed: ${completedTask.exception}")
            }
        } catch (e: ApiException) {
            println("AUTH Failed to authenticate using Google OAuth: " + e.message)
        }
    }
    return startAutocomplete
}

And for Facebook it is this:

LoginManager.getInstance().registerCallback(
    callbackManager,
    object : FacebookCallback<LoginResult> {
        override fun onSuccess(result: LoginResult) {
            val accessToken = result.accessToken
            coroutineScope.launch {
                loginViewModel.signInWithFacebookLogin(accessToken.token)
                loginViewModel.getUserType = true
                loginViewModel.loginStatus = "in"
                FirebaseMessaging.getInstance().token.addOnCompleteListener {
                    loginViewModel.insertFCMWhenLogin(it.result)
                }
            }
        }

        override fun onCancel() {
            println("AUTH Cancelled Facebook login")
            loginViewModel.loadingLogin = false
        }

        override fun onError(error: FacebookException) {
            println("AUTH Failed to authenticate with Facebook: ${error.message}")
            loginViewModel.loadingLogin = false
        }
    },
)

This is the insertFCMWhenLogin function:

fun insertFCMWhenLogin(token: String) {
    viewModelScope.launch(Dispatchers.IO) {
        try {
            repo.insertFCMWhenLogin(token)
        } catch (exp: Exception) {
            println("FCM token error")
        }
    }
}

Solution

  • You are using runBlocking to be able to use loginViewModel functions. This is probably the reason why you are getting some lag on the UI. ViewModels should not expose suspend functions.

    For example, if you have this in your ViewModel:

    suspend fun signInWithFacebookLogin() {
        
        // Async func
        
    }
    

    Change it to this:

    fun signInWithFacebookLogin() {
        
        viewModelScope.launch(Dispatchers.IO) {
    
            // Async func
            
        }
    
    }