KMP Compose调用AlertDialog报错:仅可在@Composable上下文执行
问题原因及解决方法
你的错误出在直接在Button的onClick回调里调用AlertDialog——虽然外层Content()是@Composable函数,但onClick的lambda是普通回调函数,不属于Composable上下文,所以不能在这里调用AlertDialog这类Composable类型的函数,这就是报错的核心原因。
正确的做法是用状态控制Dialog的显示,而非在点击事件里直接创建Dialog。你已经定义了openDialog状态但未合理利用,按以下方式修改代码即可解决:
修正后的核心代码逻辑
@Composable override fun Content() { val navigator = LocalNavigator.currentOrThrow // 新增状态:控制弹窗显示、存储错误提示信息 val openErrorDialog = remember { mutableStateOf(false) } val errorMsg = remember { mutableStateOf("") } val realm = openPelletRealm() val pelletLots: RealmResults<PelletLot> = retrieveAllPellotLots(realm) MaterialTheme { Column(/* 原有布局代码保持不变 */) { // 原有列表、输入框等代码保持不变 Row(/* 按钮行布局保持不变 */) { Button(onClick = { closePelletRealm(realm) navigator.pop() }) { Text("Back") } Button(onClick = { var hasError = false for ((index, _) in textFields.withIndex()) { val inputNum = textFields[index].value.toIntOrNull() ?: 0 if (pelletLots[index].numberOfPelletsInLot < inputNum) { // 仅修改状态,触发弹窗显示 errorMsg.value = "批次${pelletLots[index].lotNumber}剩余颗粒不足" openErrorDialog.value = true hasError = true break // 找到第一个错误即停止循环 } } // 无错误时才执行后续操作 if (!hasError) { closePelletRealm(realm) navigator.pop() } }) { Text("Submit") } } } // 在Composable上下文内,根据状态控制弹窗显示 if (openErrorDialog.value) { AlertDialog( onDismissRequest = { openErrorDialog.value = false }, title = { Text(text = "操作错误") }, text = { Text(errorMsg.value) }, confirmButton = { Button(onClick = { openErrorDialog.value = false }) { Text("确认") } } ) } } }
关键修改点
- 将
AlertDialog从onClick回调中移出,放到Composable的UI树结构里,用openErrorDialog状态控制显示/隐藏 - 在
onClick回调中仅做业务逻辑判断,发现错误时修改状态变量,而非直接创建Dialog - 只有当所有校验通过时,才执行关闭Realm和页面返回的操作
这种写法既符合Composable的调用规则,也能正确实现错误提示的功能。
内容的提问来源于stack exchange,提问作者user443654
相关产品推荐
相关产品推荐

