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 Row
s or Card
s 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
.