https://kotlinlang.org logo
#compose
Title
# compose
c

Colton Idle

12/05/2020, 8:39 AM
I have a list that I want to display, but each item in the list consists of a header and a sub list. This works, but I don't think the inner forEach loop is done correctly (this looks like it's not recycling the inner list)
Copy code
LazyColumn {
    item {
        Text("MAIN HEADER")
    }
    items(mylist.sections) { section: MyClass.Section ->
        Text(section.title)
        section.subsections.forEach {
            Text(it.body)
        }
    }
}
this does not work, but it's what I expected I should do
Copy code
LazyColumn {
    item {
        Text("MAIN HEADER")
    }
    items(mylist.sections) { section: MyClass.Section ->
        Text(section.title)
        item(sec.subsections) {
            Text(it.body)
        }
    }
}
a

Andrey Kulikov

12/05/2020, 1:37 PM
Copy code
LazyColumn {
    item {
        Text("MAIN HEADER")
    }
    mylist.sections.forEach { section: MyClass.Section ->
        item {
            Text(section.title)
        }
        items(section.subsections) {
            Text(it.body)
        }
    }
}
c

Colton Idle

12/05/2020, 9:19 PM
@Andrey Kulikov OOooh! I did not think of that. I'll try it now!
It worked! Thank you so much
@Andrey Kulikov I ran into this scenario again... and I can't help but question why this works? According to the docs, I thought I had to use the "DSL" of item{} or items{} https://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/package-summary#top-level-functions
The vertically scrolling list that only composes and lays out the currently visible items. The content block defines a DSL which allows you to emit items of different types. For example you can use LazyListScope.item to add a single item and LazyListScope.items to add a list of items.
Why does mylist.sections.ForEach work here? Edit: Bonus if you can point me towards a doc or a sample that shows that this is the recommended way?
a

Andrey Kulikov

01/19/2021, 11:26 AM
you just use a regular kotlin’s for each iteration and invoke functions.
Copy code
mylist.sections.forEach { section: MyClass.Section ->
        item {
            Text(section.title)
        }
        items(section.subsections) {
            Text(it.body)
        }
    }
is the same as doing something like
Copy code
item {
        Text(mylist.sections[0].title)
    }
    items(mylist.sections[0].subsections) {
        Text(it.body)
    }
    item {
        Text(mylist.sections[1].title)
    }
    items(mylist.sections[1].subsections) {
        Text(it.body)
    }
    ... and so on
c

Colton Idle

01/19/2021, 1:40 PM
Interesting. Yeah, it makes sense when you explain it that way. Thanks @Andrey Kulikov
@Andrey Kulikov I feel like I should explain my reasoning why it would be bad to use a for loop. My team is trying to grasp Column vs LazyColumn. and so we associate a for loop for Column which does not "recycle" and so when we use LazyColumn (according to the docs) we should use the "LazyColumn DSL" and so it felt wrong to use a for loop.
a

Andrey Kulikov

01/19/2021, 2:45 PM
yeah. it is reasonable. more importantly is what you do inside the for each. in Column you emit real composables inside it. so you have to compose everything. in this DSL you provide lambda factories and the LazyColumn implementation can compose only the visible ones
c

Colton Idle

01/19/2021, 2:52 PM
@Andrey Kulikov thanks. That actually means a lot. 😄 Nice to know I'm not going crazy in my line of thinking. So basically in a LazyColumn as long as everything that actually spits out a composable is wrapped in
item
or
items
then you will get "recycling"?
a

Andrey Kulikov

01/19/2021, 2:53 PM
there is no recycling anymore technically. but there is “laziness”. that is why it is LazyColumn, not RecyclerColumn 🙂
c

Colton Idle

01/19/2021, 2:55 PM
Got it. So to correct myself. Does this sound about right? @Andrey Kulikov "So it doesn't matter what kind of loop/iterator I have in a LazyColumn... everything will be lazy as long as the thing that emits a Composable is wrapped in either
item
or
items
"
a

Andrey Kulikov

01/19/2021, 3:01 PM
correct. the only incorrect usage is
Copy code
LazyColumn {
    item {
          list.forEach {
               Text(it)
          }
    }
}
because here we compose everything in one “item” call, so there is no laziness
c

Colton Idle

01/19/2021, 3:03 PM
Aha. Yeah. I wonder if a lint check or something like this could/should be spelled out more in the docs. Thanks so much @Andrey Kulikov I'm like 10000x more comfortable with LazyColumn now. Thank you!!!
2 Views