Home > Blockchain >  When Can I Use A Composable in the Scope of a LazyList or Column?
When Can I Use A Composable in the Scope of a LazyList or Column?

Time:03-25

I have built a number of projects and components with Jetpack Compose. I've read the docs and other tutorials, sites, and posts on StackOverFlow.

I am unclear about when I am allowed to use composables and composable functions inside of another composable, particularly with a LazyColumn.

I have components where I use a Row or a Column inside of a LazyColumn. Other times I try to create an itemsIndexed list that creates a series of Rows or Cards and I get an error that @Composable invocations can only happen from the context of a @Composable function.

Isn't the LazyColumn considered a @Composable function? The entire LazyColumn is within a @Composable function itself.

I'm confused about where the context changes from a composable environment to a non-composable environment.

Can anyone explain? What am I confusing?

CodePudding user response:

@Composable invocations can only happen from the context of a @Composable function

As this says you need to call a Composable from a function that is annotated with @Composable

If you check LazyColumn function signature

@Composable
fun LazyColumn(
    // rest of the params
    content: LazyListScope.() -> Unit
) {

}

You will see that content is not a Composable. On the other hand items function use itemContent as Composable

inline fun <T> LazyListScope.items(
    items: List<T>,
    noinline key: ((item: T) -> Any)? = null,
    noinline contentType: (item: T) -> Any? = { null },
    crossinline itemContent: @Composable LazyItemScope.(item: T) -> Unit
) = items(
    count = items.size,
    key = if (key != null) { index: Int -> key(items[index]) } else null,
    contentType = { index: Int -> contentType(items[index]) }
) {
    itemContent(items[it])
}

Because of this you can call Composable functions like Column inside item function.

items(myItems) { myItem: MyItem ->
    Column{

    }
}

Functions like Column, Row or Box have their XScope functions marked with @Composable

@Composable
inline fun Column(
    modifier: Modifier = Modifier,
    verticalArrangement: Arrangement.Vertical = Arrangement.Top,
    horizontalAlignment: Alignment.Horizontal = Alignment.Start,
    content: @Composable ColumnScope.() -> Unit
) {
    val measurePolicy = columnMeasurePolicy(verticalArrangement, horizontalAlignment)
    Layout(
        content = { ColumnScopeInstance.content() },
        measurePolicy = measurePolicy,
        modifier = modifier
    )
}

And because of this you can call another Composable inside a Column, Row or Box.

  • Related