Jetpack Compose的AlertDialog错误:"@Composable调用只能发生在@Composable函数的上下文中"。

5

在stackoverflow上,似乎有无数种可能解决此错误的方法,但都未能解决我的问题。

我正在构建一个组合警报对话框。我试图显示一个选项列表,这个列表可以根据数据而改变。

对话框

@Composable
fun OptionSelectComposeDialog(
   vm: OptionSelectDialogViewModel
){
...
val optionList = vm.optionList
Column {
    if (openDialog.value) {
        AlertDialog(
            ...
            text = {
                OptionListDialogContent(optionList)
            },
            ...
        )
    }
}

OptionListDialogContent 组合函数中,我试图输出列表,但是 Text 组合函数出现了错误。
@Composable
fun OptionListDialogContent(optionList: OptionList?) {

    val optionItemArray = optionList?.getOptionItemArray(null)

    LazyColumn() {
        if (optionItemArray != null) {
            optionItemArray.forEach { optionItem ->
                Text(text = optionItem.toString()) // Error "@Composable invocations can only happen from the context of a @Composable function"
            }
        }
    }
}

我怀疑在 optionItem 上进行的 toString 调用会导致此错误,因此我尝试将数组映射为字符串来转换数组值,但仍然收到此错误。

将数组转换为字符串后的 OptionListDialogContent

@Composable
fun OptionListDialogContent(optionList: OptionList?) {

    val optionItemArray = optionList?.getOptionItemArray(null)
    val optionItemStringArray = optionItemArray?.map { it.toString()}?.toTypedArray()

    LazyColumn() {
        if (optionItemStringArray != null) {
            optionItemStringArray.forEach { optionItem ->
                Timber.d("This is working? - optionItemArray.size: %s", optionItemArray.size)
                Text(text = optionItem) // Error "@Composable invocations can only happen from the context of a @Composable function"
            }
        }
    }
}

有人看到问题出在哪了吗?(我已经验证了optionItemArray不是null)
2个回答

4
原来问题出在我使用LazyColumn时的方式上。LazyColumn需要接收一个数组大小。有不同的方法可以实现这一点,但这是我采用的方式:
LazyColumn() {
    if (optionItemStringArray != null) {
        items(optionItemStringArray.size) { i ->
            Row() {
                Text(text = optionItemStringArray[i])
            }
        }
    }
}

1
是的,这是正确的解决方案,但并不是因为“LazyColumn需要接收一个数组大小”。问题在于,如果您只是像您尝试的那样调用您的组合函数,它将不会是“惰性”的。那些带有组合lambda的item()items()函数只是向LazyColumn通知项目,并允许它仅在需要时实际组合它们。 - Jan Bína
有趣。那么这个非懒惰版本会是什么样子? - petestmart
那将是一个普通的“Column”。在“Column”内部,您可以使用简单的for循环并直接调用原始的“Text”组合。 - Jan Bína
我在原始帖子中尝试将Text组件直接作为LazyColumn的子元素进行渲染,而不是将其包装在一个item中,导致出现了错误。我认为item是不必要的,但事实证明它是必要的! - Marc Fearby

0

您正在尝试将一个懒惰列表(位于OptionListDialogContent中)放入文本字段中

text = {
                OptionListDialogContent(optionList)
       },

参数需要兼容以接受可组合的函数。在本例中,该文本未满足要求。

那么,在Compose中,文本列表不被视为文本? - petestmart
1
在显示列表中的文本之前,您必须使用LazyColumn。这是一个可组合函数,文本块无法理解。 - Narendra_Nath
呃,我试图做一个自定义对话框,但它也出现了同样的问题。看起来这是与LazyColumn有关的问题。 - petestmart
告诉我你想要达到什么目的。如果你想要弹出对话框,你应该做……让我编辑我的答案。 - Narendra_Nath
是的,事实证明LazyColumn需要不同的信息。在迭代之前,它需要知道数组的大小。 - petestmart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接