Same value was passed as the nextKey in two sequential Pages loaded from a PagingSource in Paging Library 3 Android

Viewed 3573

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)
    }
}
1 Answers

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.
    )
}
Related