英文:
Understanding @compose calling
问题
我有以下的@composable
函数:
@Composable
fun MessageCard(msg: Message){
//元素
}
我注意到这段代码:
@Composable
fun Conversation(messages: List<Message>) {
LazyColumn {
for(message in messages){
MessageCard(message)
}
}
}
报错:@Composable invocations can only happen from the context of a @Composable function
然而,另一方面,
@Composable
fun Conversation(messages: List<Message>) {
LazyColumn {
items(messages) { message ->
MessageCard(message)
}
}
}
却可以正常工作(这段代码来自官方的Google文档)。
将LazyColumn
更改为Column
后,两种方法都可以工作。
查看文档后,我觉得LazyColumn
和Column
都是可组合的函数,所以这里到底发生了什么。提前谢谢。
英文:
I have the following @composable
function:
@Composable
fun MessageCard(msg: Message){
//Elements
}
And have observed that this piece of code :
@Composable
fun Conversation(messages: List<Message>) {
LazyColumn {
for(message in messages){
MessageCard(message)
}
}
}
complains about : @Composable invocations can only happen from the context of a @Composable function
While on the other hand,
@Composable
fun Conversation(messages: List<Message>) {
LazyColumn {
items(messages) { message ->
MessageCard(message)
}
}
}
Works just fine (it's taken from the official google docs).
By changing the LazyColumn
into Column
, both approaches work.
Looking through the docs it seemed to me like both LazyColumn
and Column
are composable functions, so what exactly is going on here.
Thanks in advance.
答案1
得分: 1
LazyRow或LazyColumns的内容具有LazyListScope接收器,但未注释为@Composable
,这样就无法调用其他Composables。
@Composable
fun LazyColumn(
// 其他参数
// 非Composable作用域
content: LazyListScope.() -> Unit
) {
// 实现细节
}
LazyColumn() { // LazyListScope
// 你不能在这里添加Composable,因为这个作用域是LazyListScope
// 它没有用@Composable注释,并且会返回编译器错误
// Row(){}
items(100) {
Row() {
}
}
}
你不能从LazyListScope调用Composable函数,但你可以在items内部调用,因为它的内容是@Composable函数。
fun item(
key: Any? = null,
contentType: Any? = null,
content: @Composable LazyItemScope.() -> Unit
) {
error("The method is not implemented")
}
你还可以查看关于Composable和非Composable函数的这个答案。
https://stackoverflow.com/a/73261429/5457853
英文:
LazyRow or LazyColumns have content with LazyListScope receiver that is not annotated with @Composable
which doesn't let you to call other Composables.
@Composable
fun LazyColumn(
// Rest of params
// Non Composable scope
content: LazyListScope.() -> Unit
) {
// Implementation details
}
LazyColumn(){ // LazyListScope
// You can't add Composable here because this scope is LazyListScope
// which is not annotated with @Composable, and returns compiler error
// Row(){}
items(100){
Row() {
}
}
}
You can't call Composable functions from LazyListScope but you can call inside items because its content is @Composable function.
fun item(
key: Any? = null,
contentType: Any? = null,
content: @Composable LazyItemScope.() -> Unit
) {
error("The method is not implemented")
}
You can also check out this answer about composable and non-composble functions.
答案2
得分: 1
从官方文档这里
惰性组件与Compose中的大多数布局不同。它们不是接受@Composable内容块参数的,允许应用程序直接发出组合项,而是提供了一个LazyListScope.()块。这个LazyListScope块提供了一个DSL,允许应用程序描述项的内容。然后,惰性组件负责根据布局和滚动位置的要求添加每个项的内容。
你只能从另一个可组合函数上下文中调用可组合函数。LazyColumn
本身的内容不是可组合函数,而是LazyListScope
。但是items()
的主体是一个可组合函数,因此你可以在items
中调用可组合函数。
希望这样能解决你的问题。
英文:
From the official documentation here
> The Lazy components are different to most layouts in Compose. Instead of accepting a @Composable content block parameter, allowing apps to directly emit composables, the Lazy components provide a LazyListScope.() block. This LazyListScope block offers a DSL which allows apps to describe the item contents. The Lazy component is then responsible for adding the each item’s content as required by the layout and scroll position.
You can only invoke a composable function from another composable function context. Content of the LazyColumn
itself is not a composible function rather it's a LazyListScope
. But items()
body is a composable function therefore you can call composable function within items
.
Hope that clears it up.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论