sqldelight
sqldelight copied to clipboard
Paging Source emitting 0 items when table is updated in some other screen which results in Scroll State being lost
Discussed in https://github.com/cashapp/sqldelight/discussions/5103
Originally posted by Vaibhav2002 March 31, 2024
I have a screen which shows a paged list of data coming from a SQL Delight table, Now when i navigate to some other screen in which I either add new data to the table or update existing one and navigate back
My whole screen scroll state is lost
When logging I found out that the LazyPagingItems<T>.itemCount
is 0, which seems to be messing up the scroll state
I'm using CashApp's Multiplatform Paging for Paging in Compose Multiplatform, and Decompose for navigation
This is an example of how my query is
fun getByReferenceIdPaged(referenceId: String) = QueryPagingSource(
countQuery = queries.countByReferenceId(referenceId),
transacter = queries,
context = Dispatchers.IO,
queryProvider = { limit, offset ->
queries.getByReferenceIdPaged(referenceId, limit, offset)
}
)
countByReferenceId:
SELECT COUNT(*) FROM PostEntity WHERE referenceId = :referenceId;
getByReferenceIdPaged:
SELECT * FROM PostEntity
WHERE referenceId = :referenceId
ORDER BY createdAt DESC
LIMIT :limit OFFSET :offset;
This is how i get the `Flow<PagingData<T>>
val replies = threads
.mapLatest { it.lastOrNull() }
.filterNotNull()
.distinctUntilChangedBy { it.id }
.mapLatest { postsRepo.getReplies(it.id) } // <--- Getting paging data from DB
.flatMapLatest { it.pagedData } // <- Flow of PagingData
.mapLatest { it.map { it.toDomain() } }
.cachedIn(componentScope)
.onIO()
.safeCatch()
.toStateFlow(componentScope, PagingData.empty())
My Lazy Column
LazyColumn(
modifier = modifier,
state = state,
contentPadding = contentPadding,
verticalArrangement = verticalArrangement,
reverseLayout = reverseLayout
) {
header?.invoke(this)
when(val loadState = loadState?.refresh) {
is LoadState.Loading -> {
if(loader!=null) item("Main Loader", content = loader)
}
is LoadState.Error -> {
item("Main Error") {
ErrorState(
error = loadState.error,
onRetryClick = items::retry,
modifier = errorModifier()
)
}
}
is LoadState.NotLoading -> {
if(items.itemSnapshotList.items.isEmpty())
emptyState?.let { item("Main Empty", content = it) }
else {
items(
count = items.itemCount,
key = key?.let(items::itemKey),
contentType = contentType?.let(items::itemContentType) ?: { null }
) {
items[it]?.let { item -> content(item) }
}
}
}
else -> Unit
}
if (loadState?.append?.endOfPaginationReached == true)
footer?.invoke(this)
}