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