Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Paging 3 #3396

Merged
merged 19 commits into from Jul 28, 2022
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 9 additions & 1 deletion extensions/android-paging3/build.gradle
@@ -1,9 +1,15 @@
plugins {
alias(deps.plugins.kotlin.jvm)
alias(deps.plugins.android.library)
alias(deps.plugins.kotlin.android)
alias(deps.plugins.publish)
alias(deps.plugins.dokka)
}

android {
namespace 'app.cash.sqldelight.paging3'
compileSdkVersion 23
}

veyndan marked this conversation as resolved.
Show resolved Hide resolved
archivesBaseName = 'sqldelight-androidx-paging3'

dependencies {
Expand All @@ -12,6 +18,8 @@ dependencies {
api deps.androidx.paging3.common

testImplementation project(':drivers:sqlite-driver')
testImplementation deps.androidx.paging3.runtime
testImplementation deps.androidx.recyclerView
testImplementation deps.truth
testImplementation deps.kotlin.test.junit
testImplementation deps.kotlin.coroutines.test
Expand Down
Expand Up @@ -33,33 +33,33 @@ internal class OffsetQueryPagingSource<RowType : Any>(
override suspend fun load(
params: LoadParams<Int>,
): LoadResult<Int, RowType> = withContext(context) {
try {
val key = params.key ?: 0
transacter.transactionWithResult {
val count = countQuery.executeAsOne()
if (count != 0 && key >= count) throw IndexOutOfBoundsException()

val loadSize = if (key < 0) params.loadSize + key else params.loadSize

val data = queryProvider(loadSize, maxOf(0, key))
.also { currentQuery = it }
.executeAsList()

LoadResult.Page(
data = data,
// allow one, and only one negative prevKey in a paging set. This is done for
// misaligned prepend queries to avoid duplicates.
prevKey = if (key <= 0L) null else key - params.loadSize,
nextKey = if (key + params.loadSize >= count) null else key + params.loadSize,
itemsBefore = maxOf(0, key),
itemsAfter = maxOf(0, (count - (key + params.loadSize))),
)
val key = params.key ?: 0
val limit = when (params) {
is LoadParams.Prepend -> minOf(key, params.loadSize)
else -> params.loadSize
}
val loadResult = transacter.transactionWithResult {
val count = countQuery.executeAsOne()
val offset = when (params) {
is LoadParams.Prepend -> maxOf(0, key - params.loadSize)
is LoadParams.Append -> key
is LoadParams.Refresh -> if (key >= count) maxOf(0, count - params.loadSize) else key
}
} catch (e: Exception) {
if (e is IndexOutOfBoundsException) throw e
LoadResult.Error(e)
val data = queryProvider(limit, offset)
.also { currentQuery = it }
.executeAsList()
val nextPosToLoad = offset + data.size
LoadResult.Page(
data = data,
prevKey = offset.takeIf { it > 0 && data.isNotEmpty() },
nextKey = nextPosToLoad.takeIf { data.isNotEmpty() && data.size >= limit && it < count },
itemsBefore = offset,
itemsAfter = maxOf(0, count - nextPosToLoad),
)
}
if (invalid) LoadResult.Invalid() else loadResult
}

override fun getRefreshKey(state: PagingState<Int, RowType>) = state.anchorPosition
override fun getRefreshKey(state: PagingState<Int, RowType>) =
state.anchorPosition?.let { maxOf(0, it - (state.config.initialLoadSize / 2)) }
}