8

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)
    }
}
Aminul Haque Aome
  • 2,261
  • 21
  • 34
  • 1
    You are setting nextKey here: `nextKey = data.lastOrNull()?.jobId`. Make sure you're not returning the same key twice here - does your backend API just return the key back to you if there's no more to load? You need to check for that and return `null` in that case. – dlam Sep 14 '20 at 16:39
  • @dlam thanks brother for your response. Backend is okey my brother. May be I made any mistake while implementing – Aminul Haque Aome Sep 15 '20 at 04:01
  • @AminulHaqueAome Hello, Did you find a solution to this issue? – amr ismail Mar 14 '21 at 22:09
  • @amrismail no brother – Aminul Haque Aome Mar 15 '21 at 11:19
  • @amrismail I'm facing the same issue just wonder if you have a solution – a-rohim Oct 08 '21 at 05:25
  • @a-rohim I forgot about that but I'm using now Paging 3 with jetpack compose and this issue didn't appear. I overrided the `keyReuseSupported` to true and go through google code lab https://developer.android.com/codelabs/android-paging#4 and it works well with me. – amr ismail Oct 12 '21 at 13:11
  • good to know will try. thank you! @amrismail – a-rohim Oct 14 '21 at 04:43

1 Answers1

3

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.
    )
}
David Wekesa
  • 89
  • 12