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

Feri Nagy

06/15/2022, 7:54 AM
We are trying to use paging together with sticky headers. But now instead of using
items(pagingItems) {}
, we have to iterate through the items manually, do
pagingItems.peek(index)
and add single
item {}
one by one:
Copy code
@Composable
fun PlainPaging(pagingItems: LazyPagingItems<Item>) {
    LazyColumn {
        items(pagingItems) { item ->
            when (item) {
                is Item.Header -> Text(text = item.title)
                is Item.Data -> Text(text = item.text)
                null -> Text("placeholder")
            }
        }
    }
}

// vs

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun StickyPaging(pagingItems: LazyPagingItems<Item>) {
    LazyColumn {
        for (index in 0 until pagingItems.itemCount) {
            when (val item = pagingItems.peek(index)) {
                is Item.Header -> stickyHeader { Text(text = item.title) }
                is Item.Data -> item { Text(text = item.text) }
                null -> item { Text("placeholder") }
            }
        }
    }
}
Is this going to have some performance implications? Is there a better way to do it? Thanks
👍 1
1
Or a more general question, is it a big deal to use
items(list) {...}
vs
list.forEach { item {...} }
?
a

Andrey Kulikov

06/15/2022, 12:19 PM
using
items
instead of
forEach
is a bit more efficient. when we lookup the index to composable mapping we will have to use a binary search in order to find a correct
item
as there are could be any amount of
item
items
calls. but for Paging use case there is no better solution for now, so probably it is ok
mind blown 1
f

Feri Nagy

06/15/2022, 2:10 PM
Oops, I just realised that I simplified the sample a bit too much - there is no call to
pagingItems.get(index)
, so it would not trigger loading. 😬 What about using
items(count) {}
? Would it be worth pre-processing the list so it could be used? Something along:
Copy code
val sectionIndices = (0 until pagingItems.itemCount).mapNotNull {
    it.takeIf { pagingItems.peek(it) is Item.Header }
}

val countBefore = sectionIndices.firstOrNull() ?: pagingItems.itemCount
items(countBefore) {
    //...
}

sectionIndices.forEachIndexed { index, section ->
    stickyHeader { Text(text = (pagingItems[section] as Item.Header).title) }

    val end = if (index == sectionIndices.lastIndex) pagingItems.itemCount else sectionIndices[index + 1]
    items(end - section) {
        // ...
    }
}
f

Filip Wiesner

04/11/2023, 10:33 AM
For future reference, there is issue for this https://issuetracker.google.com/issues/193785330
298 Views