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

解决@Composable仅能在@Composable函数上下文调用的编译错误

编译错误修复:@Composable invocations can only happen from the context of a @Composable function

错误原因

clickable修饰符的点击回调是普通非Composable上下文,不允许直接调用被@Composable注解标记的组件函数。你当前代码在Card的点击回调里直接调用Alert()组件,触发了这个编译限制。
Jetpack Compose是状态驱动的UI框架,弹窗这类条件显示的组件不能在事件回调里直接插入构图树,必须通过状态变量控制组件是否在Composable上下文里被渲染。

修复步骤

  • 将控制弹窗显示的状态变量从Alert()组件内部上移到Screen_A的Composable作用域中
  • Card的点击回调里仅修改弹窗状态为显示,不直接调用Alert组件
  • 将Alert组件放置在Screen_A的Composable构图层级中,根据状态值判断是否渲染
  • 给Alert组件传入关闭回调,在触发关闭操作时修改状态为隐藏

修正后代码

@Composable
fun Screen_A_with_WithTopBar(navController: NavController) {
    Scaffold(
        topBar = {
            TopAppBar(
                title = {
                    Text(text = "Top App Bar")
                },
                navigationIcon = {
                    IconButton(onClick = {
                        navController.navigate(Screen.Home.route)
                    }) {
                        Icon(Icons.Filled.Menu, "backIcon")
                    }
                },
                backgroundColor = MaterialTheme.colors.primary,
                contentColor = Color.White,
                elevation = 10.dp
            )
        }, content = {
            Screen_A(navController)
        }
    )
}

@Composable
fun Screen_A(navController: NavController) {
    val context = LocalContext.current
    // 弹窗显示状态上移到此处,初始为不显示
    val openDialog = remember { mutableStateOf(false) }

    Column(
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier
            .fillMaxSize()
    ) {

        Text(
            text = "Dooro",
            fontSize = 42.sp
        )

        Spacer(modifier = Modifier.height(33.dp))

        Row(
            verticalAlignment = Alignment.Top,
            horizontalArrangement = Arrangement.SpaceAround,
            modifier = Modifier
                .fillMaxWidth()
                .padding(12.dp),
        ) {

            Card(
                modifier = Modifier
                    .width(150.dp)
                    .height(80.dp)
                    .clickable {
                        // 点击仅修改状态,不直接调用Composable组件
                        openDialog.value = true
                    },
                shape = RoundedCornerShape(7.dp),
                elevation = 7.dp
            ) {
                Text(
                    text = "None",
                    fontSize = 24.sp,
                    fontWeight = FontWeight.Bold,
                    textAlign = TextAlign.Center
                )
            }
        } // END Row
    }

    // 在Composable上下文里根据状态渲染弹窗
    if (openDialog.value) {
        Alert(
            onDismiss = { openDialog.value = false }
        )
    }
}

// 弹窗组件改为接收关闭回调,不自己持有显示状态
@Composable
fun Alert(onDismiss: () -> Unit) {
    AlertDialog(
        onDismissRequest = onDismiss,
        title = {
            Text(text = "Title")
        },
        text = {
            Text(
                "This area typically contains the supportive text " +
                        "which presents the details regarding the Dialog's purpose."
            )
        },
        buttons = {
            Row(
                modifier = Modifier.padding(all = 8.dp),
                horizontalArrangement = Arrangement.Center
            ) {
                Button(
                    modifier = Modifier.fillMaxWidth(),
                    onClick = onDismiss
                ) {
                    Text("Dismiss")
                }
            }
        }
    )
}

额外说明:如果使用Compose 1.0+版本,也可以用rememberSaveable替代remember保存弹窗状态,避免屏幕旋转等配置变更后状态丢失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 09:12:19