Jetpack Compose点击按钮后如何从Composable函数返回PscEntity实例
问题原因分析
你当前的写法不符合Jetpack Compose的声明式编程逻辑,报错的核心原因有两个:
Button的onClick回调是无返回值的() -> Unit类型,你在回调内部写的return只能退出当前onClicklambda,根本无法将PscEntity实例返回到外层的showAlertDialog函数@Composable函数是在界面重组时同步执行的,而用户点击按钮是异步触发的交互事件,不可能让@Composable函数暂停等待用户操作后再同步返回结果
最优解决方案:回调传值
这是Compose中处理交互返回结果的标准实现方式,不需要额外定义全局变量存值,逻辑清晰无副作用:
第一步 修改showAlertDialog函数
移除返回值,新增结果回调参数,同时补充对话框显隐控制逻辑:
@Composable fun showAlertDialog( code: String, money: Double, onDismiss: () -> Unit, // 关闭对话框的回调 onConfirm: (PscEntity) -> Unit, // 确认选择的结果回调 onCancel: (PscEntity) -> Unit // 取消选择的结果回调 ) { var newCode by remember { mutableStateOf(code) } var newMoney by remember { mutableStateOf(money) } Box(contentAlignment = Alignment.Center) { Column() { TextField( value = newCode, onValueChange = { newCode = it } ) TextField( value = newMoney.toString(), onValueChange = { // 这里优化下,避免输入非数字内容崩溃 it.toDoubleOrNull()?.let { value -> newMoney = value } } ) Row() { Button(onClick = { onConfirm(PscEntity(code = newCode, money = newMoney)) onDismiss() }) { Text("Apply changes") } Button(onClick = { onCancel(PscEntity(code = code, money = money)) onDismiss() }) { Text("Disregard changes") } } } } }
第二步 修改调用层代码
在调用位置定义对话框显隐状态,在回调中接收PscEntity结果处理即可:
// 调用层添加对话框显隐控制状态 var showDialog by remember { mutableStateOf(false) } // 可选:如果需要保存返回的PscEntity可以定义这个变量 var selectedPscEntity by remember { mutableStateOf<PscEntity?>(null) } Card( modifier = Modifier .fillMaxWidth() .shadow(40.dp) .clickable { showDialog = true } ) // 显隐控制对话框 if (showDialog) { showAlertDialog( code = "11111", money = 12.32, onDismiss = { showDialog = false }, onConfirm = { entity -> // 这里拿到确认后的PscEntity做后续处理 selectedPscEntity = entity // 其他业务逻辑 }, onCancel = { entity -> // 这里拿到取消后的PscEntity做后续处理 selectedPscEntity = entity // 其他业务逻辑 } ) }
可选方案:挂起函数同步返回结果
如果你确实需要类似同步调用获取返回值的体验,可以结合协程实现:
suspend fun showAlertDialog( code: String, money: Double, showDialog: (Boolean) -> Unit ): PscEntity = suspendCancellableCoroutine { cont -> // 内部封装Composable回调,点击后通过cont.resume返回结果 // 调用时需要在协程作用域中执行,比如点击事件用launch包裹 }
内容的提问来源于stack exchange,提问作者JustSightseeing
相关产品推荐
相关产品推荐

