LazyColumn调用@Composable函数报错:仅可在@Composable上下文执行
解决Jetpack Compose中LazyColumn遍历调用Composable的错误
问题描述
实现了@Composable组件CategoryItem用于展示带下拉菜单的类别行,但在LazyColumn中遍历列表levels生成组件时,出现错误:@Composable invocations can only happen from the context of a @Composable function。
错误代码
LazyColumn( modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(8.dp) ) { levels?.forEach { category -> CategoryItem(category) // 报错位置 } }
CategoryItem实现
@Composable fun CategoryItem(category: Category) { var expanded by remember { mutableStateOf(false) } Column( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp) ) { ClickableSquare( onClick = { expanded =!expanded }, text = category.name ) if (expanded) { DropdownMenu( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp), expanded = expanded, onDismissRequest = { expanded = false } ) { category.levels.forEach { level -> DropdownMenuItem( text = { Text(text = level.name) }, onClick = { // Navigate to GameScreen with level data navController.navigate(route = AppScreens.GameScreen.route + "/${level.code}") } ) } } } } }
错误原因
LazyColumn的代码块属于LazyListScope作用域,并非标准的@Composable上下文。直接使用普通forEach遍历并调用@Composable函数,会脱离Composable上下文约束,触发报错。
解决方案
使用LazyColumn提供的items或itemsIndexed方法遍历列表,这些方法内部维护了Composable上下文,可安全调用@Composable组件。
修改后的代码
LazyColumn( modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(8.dp) ) { levels?.let { categories -> items(categories) { category -> CategoryItem(category) } } }
若需要使用列表索引,可改用itemsIndexed:
LazyColumn( modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(8.dp) ) { levels?.let { categories -> itemsIndexed(categories) { index, category -> CategoryItem(category) } } }
内容的提问来源于stack exchange,提问作者Ángel David Gutierrez Orellana
相关产品推荐
相关产品推荐

