-
Notifications
You must be signed in to change notification settings - Fork 495
/
KeyedQueryPagingSource.kt
61 lines (51 loc) · 2.1 KB
/
KeyedQueryPagingSource.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package app.cash.sqldelight.paging3
import androidx.paging.PagingState
import app.cash.sqldelight.Query
import app.cash.sqldelight.Transacter
import kotlinx.coroutines.withContext
import kotlin.coroutines.CoroutineContext
internal class KeyedQueryPagingSource<Key : Any, RowType : Any>(
private val queryProvider: (beginInclusive: Key, endExclusive: Key?) -> Query<RowType>,
private val pageBoundariesProvider: (anchor: Key?, limit: Long) -> Query<Key>,
private val transacter: Transacter,
private val context: CoroutineContext,
) : QueryPagingSource<Key, RowType>() {
private var pageBoundaries: List<Key>? = null
override val jumpingSupported: Boolean get() = false
override fun getRefreshKey(state: PagingState<Key, RowType>): Key? {
val boundaries = pageBoundaries ?: return null
val last = state.pages.lastOrNull() ?: return null
val keyIndexFromNext = last.nextKey?.let { boundaries.indexOf(it) - 1 }
val keyIndexFromPrev = last.prevKey?.let { boundaries.indexOf(it) + 1 }
val keyIndex = keyIndexFromNext ?: keyIndexFromPrev ?: return null
return boundaries.getOrNull(keyIndex)
}
override suspend fun load(params: LoadParams<Key>): LoadResult<Key, RowType> {
return withContext(context) {
try {
transacter.transactionWithResult {
val boundaries = pageBoundaries
?: pageBoundariesProvider(params.key, params.loadSize.toLong())
.executeAsList()
.also { pageBoundaries = it }
val key = params.key ?: boundaries.first()
require(key in boundaries)
val keyIndex = boundaries.indexOf(key)
val previousKey = boundaries.getOrNull(keyIndex - 1)
val nextKey = boundaries.getOrNull(keyIndex + 1)
val results = queryProvider(key, nextKey)
.also { currentQuery = it }
.executeAsList()
LoadResult.Page(
data = results,
prevKey = previousKey,
nextKey = nextKey,
)
}
} catch (e: Exception) {
if (e is IllegalArgumentException) throw e
LoadResult.Error(e)
}
}
}
}