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

Jetpack Compose中SimpleAlertDialog的Composable上下文调用错误

解决Jetpack Compose中在非Composable回调内调用Composable组件的错误

你遇到的错误核心原因是:combinedClickable的onLongClick是普通Lambda回调,不属于@Composable上下文,而SimpleAlertDialog是带@Composable注解的组件,必须在其他@Composable函数或标记了@Composable的Lambda中调用。

解决方案

正确的做法是用状态变量控制对话框的显示/隐藏,而非直接在回调内调用Composable组件。具体实现如下:

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun MyCharactersListRowView(
    viewmodel: MainViewModel,
    characterModel: CharacterModel,
    popBack: () -> Unit
) {
    val (characterSelected, setCharacterSelected) = remember { mutableStateOf<CharacterModel?>(null) }
    val openDialog = remember { mutableStateOf(false) }

    // 将对话框放在Composable顶层,由openDialog状态控制显示
    SimpleAlertDialog(
        hero = characterSelected,
        show = openDialog.value,
        onConfirm = {
            characterSelected?.let { selected ->
                viewmodel.deleteCharacter(selected.id.toLong())
                Log.d("info", "rowAffected: ${viewmodel.rowAffected.value}")
                val context = LocalContext.current
                if (viewmodel.rowAffected.value.toInt() != 0) {
                    Toast.makeText(
                        context,
                        "¡ ${selected.name} 删除成功!",
                        Toast.LENGTH_LONG
                    ).show()
                } else {
                    Toast.makeText(
                        context,
                        viewmodel.loadError.value,
                        Toast.LENGTH_LONG
                    ).show()
                }
                openDialog.value = false
            }
        },
        onDismiss = { openDialog.value = false },
        textTittle = "Remove character",
        textDescription = characterSelected?.let { "Would you like to remove ${it.name} from your characters?" } ?: ""
    )

    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(onClick = { setCharacterSelected(characterModel) })
            .padding(vertical = 8.dp, horizontal = 16.dp),
        verticalAlignment = Alignment.CenterVertically
    ){
        AsyncImage(
            model = characterModel.image,
            contentDescription = characterModel.name,
            contentScale = ContentScale.Fit,
            modifier = Modifier
                .size(60.dp)
                .clip(CircleShape)
                .combinedClickable(
                    onLongClick = {
                        // 仅更新状态,不直接调用Composable
                        setCharacterSelected(characterModel)
                        openDialog.value = true
                    },
                    onClick = {
                        // TODO: 处理点击逻辑
                    }
                )
        )
        Text(
            text = characterModel.name,
            modifier = Modifier.padding(start = 16.dp)
        )
    }
}

关键改动说明

  • 将SimpleAlertDialog移到MyCharactersListRowView的顶层,确保处于Composable上下文内,符合组件调用规则。
  • onLongClick回调仅负责更新状态变量,不再直接调用Composable组件,逻辑更简洁合规。
  • 用let安全处理characterSelected为空的潜在问题,避免空指针异常。
  • 简化原代码中冗余的链式调用,提升逻辑可读性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 22:45:53