Monday 2 August 2021

Android Paging 3 leading to duplicate rows

I was trying out the Paging 3.0.1 version. The API calls are happening right when I printed the log. But the data shown is duplicate. Could someone tell me where I went wrong?

Page data source class

class MyPageDataSource(private val api: RetrofitInstance) :
PagingSource<Int, APIDataResponse>() {

override suspend fun load(params: LoadParams<Int>): LoadResult<Int, APIDataResponse> {
    return try {
        val nextPageNumber = params.key ?: FIRST_PAGE_NUMBER
        val response = api.getData(nextPageNumber, PAGE_SIZE)
        LoadResult.Page(
            data = response.APIS!!,
            prevKey = if (nextPageNumber > FIRST_PAGE_NUMBER) nextPageNumber - 1 else null,
            nextKey = if (nextPageNumber * PAGE_SIZE < response.total!!) nextPageNumber + 1 else null
        )
    } catch (e: Exception) {
        LoadResult.Error(e)
    }
}

override fun getRefreshKey(state: PagingState<Int, APIDataResponse>): Int? {
    return state.anchorPosition
}

companion object {
    const val FIRST_PAGE_NUMBER = 1
    const val PAGE_SIZE = 20
}
}

Adapter:

class MyListingAdapter() : PagingDataAdapter<APIDataResponse, MyListingAdapter.MyViewHolder>(MyComparator) {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
    return MyViewHolder(
        FragmentItemBinding.inflate(
            LayoutInflater.from(parent.context),
            parent,
            false
        )
    )
}

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
    holder.bind(item = getItem(position))
}

inner class MyViewHolder(binding: FragmentItemBinding) :
    RecyclerView.ViewHolder(binding.root) {
    private val title: TextView = binding.title

    fun bind(item: APIDataResponse?) {
        if(item != null) {
            title.text = item.title
        }
    }
}

object MyComparator : DiffUtil.ItemCallback<APIDataResponse>() {
    override fun areItemsTheSame(
        oldItem: APIDataResponse,
        newItem: APIDataResponse
    ): Boolean {
        return oldItem.id == newItem.id
    }

    override fun areContentsTheSame(
        oldItem: APIDataResponse,
        newItem: APIDataResponse
    ): Boolean {
        return oldItem == newItem
    }
}
}

View Model:

class PagingViewModel : ViewModel() {

fun getData() : Flow<PagingData<APIDataResponse>> {
    return Pager(
        PagingConfig(
            pageSize = 20,
            enablePlaceholders = false,
            maxSize = 40,
            initialLoadSize = 20,
            prefetchDistance = 10
        )
    ) {
        MyPageDataSource(RetrofitInstance())
    }.flow.cachedIn(viewModelScope)
}
}

Recycler view setting up in the fragment:

val myAdapter = MyListingAdapter(myActivity)

    //Setup the recyclerview
    binding.myList.apply {
        layoutManager = when {
            columnCount <= 1 -> LinearLayoutManager(context)
            else -> GridLayoutManager(context, columnCount)
        }
        myAdapter.stateRestorationPolicy = RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY
        val decoration =
            DividerItemDecoration(myActivity, DividerItemDecoration.VERTICAL)
        addItemDecoration(decoration)
        setHasFixedSize(true)
        adapter = myAdapter
    }
    lifecycleScope.launch {
        viewModel.getData().distinctUntilChanged().collectLatest { pagedData ->
            myAdapter.submitData(pagedData)
        }
    }


from Android Paging 3 leading to duplicate rows

No comments:

Post a Comment