I migrated from paging 2 to paging 3. I tried to implement ItemKeyedDataSource of Paging 2 to Paging library 3. But the problem I was facing is, the same value(currentJodId) was passed as the nextkey in two sequential Pages loaded. And After that app crashes. but if I add "keyReuseSupported = true" in DataSource, app does not crash. But it started calling same item id as the nextkey.
JobSliderRestApi.kt
@GET("job/list/slides")
fun getDetailOfSelectedJob(
@Query("current_job") currentJodId: Int?,
@Query("limit") jobLimit: Int?,
@Query("search_in") fetchType: String?
): Single<Response<JobViewResponse>>
JobViewResponse.kt
data class JobViewResponse(
@SerializedName("data") val data: ArrayList<JobDetail>?
) : BaseResponse()
JobDetail.kt
data class JobDetail(
@SerializedName("job_id") val jobId: Int,
@SerializedName("tuition_type") val jobType: String?,
@SerializedName("class_image") val jobImage: String,
@SerializedName("salary") val salary: String,
@SerializedName("no_of_student") val noOfStudent: Int,
@SerializedName("student_gender") val studentGender: String,
@SerializedName("tutor_gender") val preferredTutor: String,
@SerializedName("days_per_week") val daysPerWeek: String?,
@SerializedName("other_req") val otherReq: String?,
@SerializedName("latitude") val latitude: Double?,
@SerializedName("longitude") val longitude: Double?,
@SerializedName("area") val area: String,
@SerializedName("tutoring_time") val tutoringTime: String?,
@SerializedName("posted_date") val postedDate: String?,
@SerializedName("subjects") val subjects: String,
@SerializedName("title") val title: String
)
JodSliderDataSource.kt
class JodSliderDataSource @Inject constructor(
private val jobSliderRestApi: JobSliderRestApi
): RxPagingSource<Int, JobDetail>() {
// override val keyReuseSupported = true
@ExperimentalPagingApi
override fun getRefreshKey(state: PagingState<Int, JobDetail>): Int? {
return state.anchorPosition?.let {
state.closestItemToPosition(it)?.jobId
}
}
override fun loadSingle(params: LoadParams<Int>): Single<LoadResult<Int, JobDetail>> {
return jobSliderRestApi.getDetailOfSelectedJob(42673, 2, "next").toSingle()
.subscribeOn(Schedulers.io())
.map { jobResponse -> toLoadResult(jobResponse.data) }
.onErrorReturn { LoadResult.Error(it) }
}
private fun toLoadResult(data: ArrayList<JobDetail>): LoadResult<Int, JobDetail> {
return LoadResult.Page(data = data, prevKey = null, nextKey = data.lastOrNull()?.jobId)
}
}
The getRefreshKey method load() (the first call is initial load which uses the initial key provided to the Pager). A refresh happens whenever the Paging library wants to load new data to replace the current list, e.g., on swipe to refresh or on invalidation due to database updates, config changes, process death, etc.
Display the paged data in your UICreate an instance of your PagingDataAdapter class. Pass the PagingDataAdapter instance to the RecyclerView list that you want to display your paged data. Observe the PagingData stream, and pass each generated value to your adapter's submitData() method.
getRefreshKey() provides a key used for the initial load for the next pagingSource due to invalidation of the existing pagingSource . The key is provided to load via LoadParams. key . The last accessed position can be retrieved via state.
{ // * prevKey == null -> anchorPage is the first page. // * nextKey == null -> anchorPage is the last page. // just return null. A typical PagingSource implementation passes parameters provided in its constructor to the load () method to load appropriate data for a query. In the example above, those parameters are:
PagingSource<Key, Value> has two type parameters: Key and Value. The key defines the identifier used to load the data, and the value is the type of the data itself. For example, if you load pages of User objects from the network by passing Int page numbers to Retrofit , you would select Int as the Key type and User as the Value type.
The PagingSource API class includes the load () method, which you must override to indicate how to retrieve paged data from the corresponding data source. Use the PagingSource class directly to use Kotlin coroutines for async loading. The Paging library also provides classes to support other async frameworks:
It allows us to load pages of data from the network or local database with ease and saves our development time. Paging3 is designed to follow the Android app architecture and coordinates with other Jetpack components.
I was getting the same error and this is what worked for me. In the JodSliderDataSource class, toLoadResult method, set the nextKey parameter value by getting the page number from the response data and adding one.
private fun toLoadResult(
data: ArrayList<JobDetail>
): LoadResult<Int, JobDetail> {
return LoadResult.Page(
data = data,
prevKey = null,
nextKey = data.lastOrNull()?.jobId + 1 // Add one to the page number here.
)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With