package com.aiosman.riderpro import androidx.paging.PagingSource import androidx.paging.PagingState import kotlinx.coroutines.delay import kotlin.math.ceil class TestBackend( private val backendDataList: List, private val loadDelay: Long = 500, ) { val DataBatchSize = 5 class DesiredLoadResultPageResponse(val data: List) /** Returns [DataBatchSize] items for a key */ fun searchItemsByKey(key: Int): DesiredLoadResultPageResponse { val maxKey = ceil(backendDataList.size.toFloat() / DataBatchSize).toInt() if (key >= maxKey) { return DesiredLoadResultPageResponse(emptyList()) } val from = key * DataBatchSize val to = minOf((key + 1) * DataBatchSize, backendDataList.size) val currentSublist = backendDataList.subList(from, to) return DesiredLoadResultPageResponse(currentSublist) } fun getAllData() = TestPagingSource(this, loadDelay) } class TestPagingSource( private val backend: TestBackend, private val loadDelay: Long, ) : PagingSource() { override suspend fun load(params: LoadParams): LoadResult { // Simulate latency delay(loadDelay) val pageNumber = params.key ?: 0 val response = backend.searchItemsByKey(pageNumber) // Since 0 is the lowest page number, return null to signify no more pages should // be loaded before it. val prevKey = if (pageNumber > 0) pageNumber - 1 else null // This API defines that it's out of data when a page returns empty. When out of // data, we return `null` to signify no more pages should be loaded val nextKey = if (response.data.isNotEmpty()) pageNumber + 1 else null return LoadResult.Page(data = response.data, prevKey = prevKey, nextKey = nextKey) } override fun getRefreshKey(state: PagingState): Int? { return state.anchorPosition?.let { state.closestPageToPosition(it)?.prevKey?.plus(1) ?: state.closestPageToPosition(it)?.nextKey?.minus(1) } } }