You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Kotlin Compose认证时CircularProgressIndicator卡顿问题

解决CircularProgressIndicator冻结问题的方案

核心问题分析

你的卡顿问题完全是主线程被阻塞导致的:

  • Google登录回调中使用runBlocking,会直接挂起主线程直到所有内部操作完成,期间UI无法刷新,ProgressIndicator自然冻结。
  • Facebook登录的协程默认在主线程执行,如果signInWithFacebookLogin包含网络/数据库等耗时操作,同样会占用主线程导致UI卡顿。

CircularProgressIndicator不需要独立线程,Compose的UI渲染本身就在主线程,只要主线程不被阻塞,它就能流畅运行。


具体代码修改

1. 修复Google登录的主线程阻塞问题

把runBlocking替换为viewModelScope.launch,避免阻塞主线程:

@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为viewModelScope.launch,避免阻塞主线程
                loginViewModel.viewModelScope.launch {
                    loginViewModel.singInWithGoogle(token)
                    loginViewModel.getUserType = true
                    loginViewModel.loginStatus = "in"
                    FirebaseMessaging.getInstance().token.addOnCompleteListener {
                        loginViewModel.insertFCMWhenLogin(it.result)
                    }
                    email?.let { loginViewModel.updateEmail(it) }
                }
            } else {
                println("AUTH Google Auth failed: ${completedTask.exception}")
            }
        } catch (e: ApiException) {
            println("AUTH Failed to authenticate using Google OAuth: " + e.message)
        }
    }
    return startAutocomplete
}

2. 确保ViewModel中的登录方法在后台线程执行

修改singInWithGoogle和signInWithFacebookLogin方法,用withContext(Dispatchers.IO)包裹耗时操作:

// 在LoginViewModel中
suspend fun singInWithGoogle(token: String) {
    withContext(Dispatchers.IO) {
        // 这里执行Firebase Google认证等耗时操作
        // 示例:firebaseAuth.signInWithCredential(GoogleAuthProvider.getCredential(token, null))
    }
}

suspend fun signInWithFacebookLogin(token: String) {
    withContext(Dispatchers.IO) {
        // 这里执行Facebook认证等耗时操作
        // 示例:firebaseAuth.signInWithCredential(FacebookAuthProvider.getCredential(token))
    }
}

3. 优化Facebook登录的协程执行

直接使用viewModelScope管理协程,避免主线程阻塞:

LoginManager.getInstance().registerCallback(
    callbackManager,
    object : FacebookCallback<LoginResult> {
        override fun onSuccess(result: LoginResult) {
            val accessToken = result.accessToken
            // 使用viewModelScope确保协程生命周期与ViewModel绑定,且不阻塞主线程
            loginViewModel.viewModelScope.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
        }
    },
)

关键注意事项

  • 永远不要在主线程执行耗时操作:网络请求、数据库操作、第三方SDK的同步认证逻辑都要放到Dispatchers.IO线程。
  • 避免使用runBlocking:它会阻塞调用线程,在UI相关代码中绝对禁止使用,改用viewModelScope.launch或lifecycleScope.launch。
  • ViewModel的suspend函数要处理线程:ViewModel中的suspend函数应该内部用withContext切换到合适的线程,对外暴露的suspend函数让调用方无需关心线程细节。

内容的提问来源于stack exchange,提问作者Cipri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 14:51:08