skip to Main Content

I know this question has been asked before, but honestly, I can’t find the right solution. I don’t know why after scrolling the RecyclerView, adapter makes same data over and over again.

I have a project that uses retrofit to get data from an api-server and show it on a RecyclerView. I’m receiving data correctly and the received list doesn’t have any repeated items. Just before passing the data to RecyclerAdapter in my Activity, I Log the data and still everything looks good. So I think the problem is the Adapter.

PS. While I’m running the app and scrolling RecyclerView to the end, "Log" inside the adapter, returns unique items. I think I have a mistake in binding data.

Log.i("test",data[position].toString())

Here is my Adapter:

import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.cocktailrecipes.apiManager.model.category
import com.example.cocktailrecipes.databinding.TemplateRecyclerViewCategoryBinding

class CategoryAdapter(private val data: List<category.Drink>) : RecyclerView.Adapter<CategoryAdapter.Holder>() {

    lateinit var binding: TemplateRecyclerViewCategoryBinding

    inner class Holder(itemView: View) :  RecyclerView.ViewHolder(itemView) {

        fun bindData(drinkData:category.Drink) {

            binding.txtDrinkName.text = drinkData.strDrink

            Glide.with(binding.root)
                .load(drinkData.strDrinkThumb)
                .into(binding.imgDrink)
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
        binding = TemplateRecyclerViewCategoryBinding.inflate(LayoutInflater.from(parent.context),parent,false)
        return Holder(binding.root)
    }

    override fun onBindViewHolder(holder: Holder, position: Int) {
        Log.i("test",data[position].toString())          
        holder.bindData(data[position])
    }

    override fun getItemCount(): Int {
        return data.size
    }
}

3

Answers


  1. Chosen as BEST ANSWER

    Thx so much @Tenfour04

    I use your advice and my problem solved:

    class CategoryAdapter(private val data: List<category.Drink>) : RecyclerView.Adapter<CategoryAdapter.Holder>() {
    
        inner class Holder(private val binding: TemplateRecyclerViewCategoryBinding) :  RecyclerView.ViewHolder(binding.root) {
    
            fun bindData(drinkData:category.Drink) {
    
                binding.txtDrinkName.text = drinkData.strDrink
    
                Glide.with(binding.root)
                    .load(drinkData.strDrinkThumb)
                    .into(binding.imgDrink)
            }
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
            val binding = TemplateRecyclerViewCategoryBinding.inflate(LayoutInflater.from(parent.context),parent,false)
            return Holder(binding)
        }
    
        override fun onBindViewHolder(holder: Holder, position: Int) {
            Log.i("test",data[position].toString())
            holder.bindData(data[position])
        }
    
        override fun getItemCount(): Int {
            return data.size
        }
    }
    

  2. For the Holder make itemView a val, and then in bindData call:
    itemView.txtDrinkName.text = drinkData.strDrink

    binding is just a class property, I am not sure how it would know what view is associate with a specific holder.

    Login or Signup to reply.
  3. here is solution:-

    @Override
    
    public long getItemId(int position) {
    
        return position;
    }
    
    @Override
    
    public int getItemViewType(int position) {
    
       return position;
    
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search