如何用Kotlin协程执行数据库请求且不冻结Compose桌面应用UI
解决方案
1. 重构loginUser为挂起函数
原函数用runBlocking会强制阻塞UI线程,直接将其改为挂起函数,利用Kotlin协程的挂起特性异步执行数据库请求:
suspend fun loginUser(data: Map<String, String>): Response { return dbRequest( Params.LoginParams( username = data["username"]!!, password = data["password"]!!, ) ) }
2. 在Compose按钮中用协程管理异步流程
使用rememberCoroutineScope创建与Composable生命周期绑定的协程作用域,在协程内处理登录逻辑并手动管理加载状态:
// 在你的登录Composable函数内声明协程作用域 val scope = rememberCoroutineScope() Button( onClick = { if (state.validate()) { scope.launch { loading.value = true try { val data = state.getData() val response = persistence.loginUser(data) as SimpleResponse // 根据响应更新UI状态 if (response.success) { loginSuccessText.value = response.message loginErrorText.value = "" } else { loginErrorText.value = response.message loginSuccessText.value = "" } } finally { // 无论请求成功/失败,确保加载状态被重置 loading.value = false } } } }, colors = ButtonDefaults.buttonColors(backgroundColor = Color(AppColours.Wisteria)), modifier = Modifier.size(100.dp, 40.dp) ) { if (loading.value) { CircularProgressIndicator(modifier = Modifier.size(20.dp)) } else { Text("Login") } }
关键说明
- 挂起函数
loginUser不会阻塞UI线程:当执行dbRequest这个挂起操作时,协程会释放UI线程,让界面保持响应。 rememberCoroutineScope确保协程与Composable生命周期同步:当Composable被销毁时,协程会自动取消,避免内存泄漏。try-finally块保证加载状态必被重置:即使请求过程中出现异常,也不会让加载动画一直显示。
内容的提问来源于stack exchange,提问作者Sebastian Villate
相关产品推荐
相关产品推荐

