androidandroid-recyclerviewpaginationandroid-paging-3android-diffutils

If data in a recycler view item is null then don't display the view holder


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: Api response

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: enter image description here

enter image description here

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: enter image description here

and in between it again shows like this: enter image description here

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

}}

Solution

  • I have solved this error by applying a condition in my paging source code enter image description here