klibs.Paging is kotlin-only lightweight paging library
See also other klibs libraries
Gradle
implementation("ru.astrainteractive.klibs:paging:<version>")
implementation(libs.klibs.paging)
Version catalogs
[versions]
klibs-paging = "<latest-version>"
[libraries]
klibs-paging = { module = "ru.astrainteractive.klibs:paging", version.ref = "klibs-paging" }
For sample see Sample directory
It contains ComposeJB RickMortyApi paging implementation with filtering
If you have issues with usage of this library - take a look into sources. Almost everything documented and designed to be easy to understand
PageContext is the description of your current page. It can contain int, string, anything. Most users describe page as Integer value, so here's example:
Factory here is used to create next or previous page context
data class LongPageContext(val page: Long) : PageContext {
object Factory : PageContext.Factory<LongPageContext> {
override fun next(pageContext: LongPageContext): LongPageContext {
return pageContext.copy(page = pageContext.page + 1)
}
}
}
Mostly you will use LambdaPagedListDataSource, but it also can be created with PagedListDataSource interface
// With interface
class BytesPagedListDataSource : PagedListDataSource<Byte, LongPageContext> {
override suspend fun getListResult(pagingState: PagingState<Byte, LongPageContext>): Result<List<Byte>> {
return runCatching { listOf(0.toByte()) }
}
}
// Or lambda
val bytesPagedListDataSource = LambdaPagedListDataSource<Byte, LongPageContext> {
runCatching { listOf(0.toByte()) }
}
For custom PageContext you need to create PagerCollector. It can be made with delegation
class LongPagerCollector<T>(
private val initialPage: Long = 0L,
private val pageSize: Int = 10,
private val pager: PagedListDataSource<T, LongPageContext>,
) : PagingCollector<T, LongPageContext> by DefaultPagingCollector(
initialPagingStateFactory = {
PagingState(
pageContext = LongPageContext(page = initialPage),
items = emptyList(),
pageSizeAtLeast = pageSize,
isLastPage = false,
isLoading = false,
isFailure = false
)
},
pager = pager,
pageContextFactory = LongPageContext.Factory
)
/**
* Your custom repository implementation
*/
class MyRepositoryImpl : MyRepository {
/**
* Define your paging collector
*/
private val pagingCollector = LongPagerCollector(
initialPage = 0,
pager = CoroutineHandledPagedListDataSource<String, LongPageContext> { pagingState ->
val page = pagingState.pageContext.page
val pageSize = pagingState.pageSizeAtLeast
if (Random.nextBoolean()) List(pagingState.pageContext.page.toInt()) { i -> "Value number ${pageSize * page} + $i" }
else error("Some error")
}
)
/**
* Define stateflow of your pager
*/
override val pagingState: StateFlow<PagingState<String, LongPageContext>> = pagingCollector.state
/**
* Add ability to reset it
*/
override suspend fun reset() {
pagingCollector.resetAndJoin()
}
/**
* Add ability to load next page
*/
override suspend fun loadNextPage() {
pagingCollector.loadNextPage()
}
}