QueryPagingSource

@JvmName(name = "QueryPagingSourceInt")
fun <RowType : Any> QueryPagingSource(countQuery: Query<Int>, transacter: TransacterBase, context: CoroutineContext, queryProvider: (limit: Int, offset: Int) -> Query<RowType>, initialOffset: Int = 0): PagingSource<Int, RowType>

Create a PagingSource that pages through results according to queries generated by queryProvider. Queries returned by queryProvider should expect to do SQL offset/limit based paging. For that reason, countQuery is required to calculate pages and page offsets. initialOffset initial offset to start paging from.

An example query returned by queryProvider could look like:

SELECT value FROM numbers
LIMIT 10
OFFSET 100;

Queries will be executed on context.


@JvmName(name = "QueryPagingSourceLong")
fun <RowType : Any> QueryPagingSource(countQuery: Query<Long>, transacter: TransacterBase, context: CoroutineContext, queryProvider: (limit: Long, offset: Long) -> Query<RowType>, initialOffset: Long = 0): PagingSource<Int, RowType>

Variant of QueryPagingSource that accepts a Long instead of an Int for countQuery , queryProvider and initialOffset.

If the result of countQuery exceeds Int.MAX_VALUE, then the count will be truncated to the least significant 32 bits of this Long value.

See also


fun <Key : Any, RowType : Any> QueryPagingSource(transacter: TransacterBase, context: CoroutineContext, pageBoundariesProvider: (anchor: Key?, limit: Long) -> Query<Key>, queryProvider: (beginInclusive: Key, endExclusive: Key?) -> Query<RowType>): PagingSource<Key, RowType>

Create a PagingSource that pages through results according to queries generated by queryProvider. Queries returned by queryProvider should expected to do keyset paging. For that reason, queries should be arranged by an non-ambigious ORDER BY clause. Key must be a unique clause that rows are ordered by. For performance reasons, an index should be present on Key.

pageBoundariesProvider is a callback that produces a query containing Key items that specifies where each page boundary exists within the full dataset. For example:

The dataset [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ordered ascending with a page size of 2 would produce page boundaries [0, 2, 4, 6, 8].

The dataset [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ordered ascending with a page size of 3 would produce page boundaries [0, 3, 6, 9].

Callbacks made from pageBoundariesProvider may include an anchor key which, if present, should appear in the resulting query.

Because page boundaries are computed ahead of time, PagingConfig.initialLoadSize should match PagingConfig.pageSize. Failing to do so will result in unexpected page sizes, as pageBoundariesProvider is called a single time during the first call to PagingSource.load on this source.

Generally, it's only feasible to produce page boundaries using SQLite window functions. An example query to generate page boundaries like shown above would look like the following.

SELECT value
FROM (
SELECT
value,
CASE
WHEN ((row_number() OVER(ORDER BY value ASC) - 1) % :limit) = 0 THEN 1
WHEN value = :anchor THEN 1
ELSE 0
END page_boundary
FROM numbers
ORDER BY value ASC
)
WHERE page_boundary = 1;

SQLite window queries became available as of version 3.25.0. For this reason, consuming applications will likely need a minSdk of 30 set or bundle a SQLite module separate from the OS provided module.

An example query returned by queryProvider could look like:

SELECT value FROM numbers
WHERE value >= :beginInclusive AND (value < :endExclusive OR :endExclusive IS NULL)
ORDER BY value ASC;

Queries will be executed on context.

This PagingSource does not support jumping. If your use case requires jumping, use the offset based QueryPagingSource function.