为何LazyColumn中直接调用@Composable函数报错,Column却正常?
核心差异:Lambda是否处于@Composable上下文
LazyColumn的content lambda无@Composable注解
LazyColumn的content参数类型是LazyListScope.() -> Unit,这个lambda本身没有被@Composable标记,不属于Composable执行上下文。直接在这个lambda里调用带@Composable注解的MessageCard,会触发@Composable invocations can only happen from the context of a @Composable function错误——因为Composable函数必须在被@Composable标记的上下文中执行。items方法提供了@Composable上下文
items是LazyListScope的扩展函数,它接收的item渲染lambda参数是@Composable (Message) -> Unit,这个lambda被@Composable注解标记,属于合法的Composable执行上下文。因此在这个lambda里调用MessageCard完全符合规则,不会报错。Column的content lambda自带@Composable上下文
Column的content参数类型是@Composable ColumnScope.() -> Unit,本身就处于@Composable上下文里。不管用for循环直接调用MessageCard还是其他方式,都在合法的Composable执行环境中,因此两种写法都能正常运行。
源码佐证(简化版)
可以通过官方源码定义验证上述逻辑:
- LazyColumn的content定义:
@Composable fun LazyColumn( // 其他参数... content: LazyListScope.() -> Unit ) - items方法的定义:
fun <T> LazyListScope.items( items: List<T>, itemContent: @Composable (T) -> Unit ) { // 内部实现 } - Column的content定义:
@Composable fun Column( // 其他参数... content: @Composable ColumnScope.() -> Unit )
内容的提问来源于stack exchange,提问作者Ait-Gacem Nabil

