I have an API which give me the list of doctors. On it's last page only 1 item is there and other items are null like this:
After this i have used paging library for pagination my pagingSource code: `
class DocPagingSource(val docRepository: DocRepository): PagingSource<Int, Data>() {
override fun getRefreshKey(state: PagingState<Int, Data>): Int? {
return state.anchorPosition?.let {
state.closestPageToPosition(it)?.prevKey?.plus(1)
?: state.closestPageToPosition(it)?.nextKey?.minus(1)
}
}
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Data> {
return try {
val currentPage = params.key?: 1
val city: String = ""
val response = docRepository.getDoctors(city, currentPage)
val page = Math.ceil(response.body()!!.total.toDouble()/5).toInt()
val data = response.body()!!.data
val responseData = mutableListOf<Data>()
responseData.addAll(data)
LoadResult.Page(
data = responseData,
prevKey = if(currentPage==1) null else -1,
nextKey = if (currentPage== page) null else currentPage.plus(1)
)
}catch (e: HttpException){
LoadResult.Error(e)
}catch (e: Exception){
LoadResult.Error(e)
}
}
` My paging Adapter Code:
class DocAdapter(val context: Context): PagingDataAdapter<Data, DocAdapter.DocViewHolder>(DiffUtil()) {
private lateinit var binding: ItemDoctorsBinding
inner class DocViewHolder : RecyclerView.ViewHolder(binding.root) {
fun bind(item: Data?) {
binding.apply {
txtDocCity.text = item?.city
txtDocName.text = item?.docName
txtDocFees.text = item?.docConsultationFee
txtDocYOE.text = item?.docYoE
txtDocSpecialisation.text = item?.docSpecialisation
Glide.with(context)
.load(item?.docProfileImgUrl)
.fitCenter()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(docPhoto)
}
}
}
override fun onBindViewHolder(holder: DocViewHolder, position: Int) {
val item = getItem(position)
if (item!=null){
holder.bind(getItem(position)!!)
holder.setIsRecyclable(false)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DocViewHolder {
val inflater = LayoutInflater.from(context)
binding = ItemDoctorsBinding.inflate(inflater, parent, false)
return DocViewHolder()
}
class DiffUtil: androidx.recyclerview.widget.DiffUtil.ItemCallback<Data>(){
override fun areItemsTheSame(oldItem: Data, newItem: Data): Boolean {
return oldItem.docId == newItem.docId
}
override fun areContentsTheSame(oldItem: Data, newItem: Data): Boolean {
return oldItem==newItem
}
}}
what I am getting after reaching my 16th item in doctor list on last page it should show entry till 16th item but after that it also shows again like this:
Also if i dont use holder.setIsRecyclable(false)
in pagingAdapter then this android icon not shown but then list is populated with previous doctors:
on the top DR. Sixteen is shown like this:
and in between it again shows like this:
My doctorViewModel Class:
class DocViewModel(val repository: DocRepository): ViewModel() {
val loading = MutableLiveData<Boolean>()
val docList = Pager(PagingConfig(5, maxSize = 100)){
DocPagingSource(repository)
}.flow.cachedIn(viewModelScope)}
My main Activity:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var docViewModel: DocViewModel
private lateinit var docAdapter: DocAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val docListRepository = DocRepository()
val docFactory = DocViewModelFactory(docListRepository)
docViewModel = ViewModelProvider(this, docFactory).get(DocViewModel::class.java)
docAdapter = DocAdapter(this)
lifecycleScope.launchWhenCreated {
docViewModel.docList.collect{
docAdapter.submitData(it)
}
}
binding.docRecyclerView.apply {
layoutManager = LinearLayoutManager(this@MainActivity)
adapter = docAdapter
setHasFixedSize(true)
}
}}