理解 @compose 的调用方式

huangapple go评论96阅读模式
英文:

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后,两种方法都可以工作。

查看文档后,我觉得LazyColumnColumn都是可组合的函数,所以这里到底发生了什么。提前谢谢。

英文:

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&lt;Message&gt;) {
    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&lt;Message&gt;) {
    LazyColumn {
        items(messages) { message -&gt;
            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.() -&gt; Unit
) {
  // Implementation details
}

LazyColumn(){ // LazyListScope
   // You can&#39;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.() -&gt; Unit
) {
    error(&quot;The method is not implemented&quot;)
}

You can also check out this answer about composable and non-composble functions.

https://stackoverflow.com/a/73261429/5457853

答案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.

huangapple
  • 本文由 发表于 2023年8月9日 07:43:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76863750.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定