Given a table with many rows, I would like to query using paging if possible. When paging I would also like to group the data based on a database column and use that column as the section header for each group.
Data Table:
Id, section, data1, data2
0, "One", 1, 2
1, "One", 2, 3
2, "Two", 40, 20
3, "Two", 11, 21
4, "Three", 110, 23
Room Query:
@Query("SELECT section, * FROM data GROUP BY section ORDER BY section ASC")
fun getData(): PagingSource<Int, DataGroup>
data class DataGroup(
@ColumnInfo(name = "section") val section: String,
@Embedded val data: Data
)
Then in compose:
@Composable
private fun Data(
viewModel: DataViewModel = hiltViewModel()
) {
viewModel.lights,
val lazyItems: LazyPagingItems<DataGroup> = viewModel.data.collectAsLazyPagingItems()
LazyColumn() {
items(lazyItems) { item: DataGroup ->
// I can iterate each item by this is not grouped
}
}
}
EDIT: Thinking about this more, I don't think a SQL "group by" is what I am after. Probably something more like:
@Query("SELECT section, * FROM data ORDER BY section ASC")
fun getData(): List<Data>
With:
val groupedData = dao.getData.groupBy { it.section }
However at that point I lose the advantage of paging. Possible to achieve this grouped by section result with paging?
It seems the paging library already has a utility to handle this. In my case:
@Query("SELECT section, * FROM data ORDER BY section ASC")
fun getData(): PagingSource<Int, Data>
Then map the data, and use insertSeparators to determine where to place the section headers:
val data: Flow<PagingData<Data>> = Pager(PagingConfig(pageSize = 20), null) {
repository.getData()
}.flow
.map { pagingData ->
mapped.insertSeparators { data1: Data?, data2: Data? ->
if (data1?.section != data2?.section) {
Data(section = data2?.section, isHeader = true)
} else null
}
}