I am trying to implement recyclerview which have a 50-100 list of item. Each row contains of TextView and Edittext view. User type comments on each row containing edittext. But the issue is that when user types the value and try to scroll up/down, data entered in the row get lost.
Then I tried another solution. I update the value of the array at that position and notifyDataSetChanged, it prints value on all row containing edittext
My Adapter:
class MyAdapter(
val context: Context,
val itemList: MutableList<String>
) :
RecyclerView.Adapter<MyAdapter.ViewHolder>() {
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
var txtLabel: TextView = view.findViewById(R.id.txtLabel)
var etValue: EditText = view.findViewById(R.id.etValue)
var watcher: TextWatcher? = null
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ViewHolder {
val view =
LayoutInflater.from(context).inflate(R.layout.list_comment, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.txtLabel.text = itemList[position]
holder.watcher = holder.etValue.doAfterTextChanged { text ->
try {
updateItem(
position,
text.toString()
)
} catch (ex: Exception) {
println(ex.message)
}
}
}
override fun getItemCount(): Int {
return itemList.size
}
fun updateItem(position: Int, item: String) {
itemList.add(position, item)
notifyDataSetChanged()
}
}
When updateItem method run it updates all rows but I am passing the position to only update at that position. Kindly guide what is the issue.
holder.etValue.doAfterTextChanged will add a TextChangedListener. You don't remove it later and thus you end up with multiple listener attached to one EditText.
You could rewrite your code like this:
class MyAdapter(
val context: Context,
val itemList: MutableList<String>
) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
lateinit var onTextUpdated: (String) -> Unit
var txtLabel: TextView = view.findViewById(R.id.txtLabel)
var etValue: EditText = view.findViewById(R.id.etValue)
init { // TextChanged listener added only once.
etValue.doAfterTextChanged { editable ->
val text = editable.toString()
onTextUpdated(text)
}
}
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ViewHolder {
val view =
LayoutInflater.from(context).inflate(R.layout.list_comment, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.txtLabel.text = itemList[position]
holder.onTextUpdated = { text -> // each time holder is bound, new listener will be assigned
try {
updateItem(
position,
text
) // update cached value
holder.txtLabel.text = text // update label
} catch (ex: Exception) {
println(ex.message)
}
}
}
override fun getItemCount(): Int {
return itemList.size
}
fun updateItem(position: Int, item: String) {
itemList[position] = item
// this might mess up the EditTexts focus.
// notifyDataSetChanged()
}
}
Related
I have a list of item in RecylerView, with have a delete button with delete the item from the list.
When I click the delete button, the item at last got deleted not the item selected to be deleted.
What's more, it creates a new item with old item's data instead of new data.
The following below is the code written in Kotlin:
class MedicineAdapter(private val activity: Activity, private val dataSet: MutableList<MedicineModel>, private val medicineSet: List<MedicineData>): RecyclerView.Adapter<MedicineAdapter.ViewHolder>() {
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val deleteLayout: LinearLayout
val medicineLayout: LinearLayout
val medicineName: TextView
val timeLayout: LinearLayout
val medicineTime: TextView
init {
deleteLayout = view.findViewById(R.id.delete_layout)
medicineLayout = view.findViewById(R.id.medicine_layout)
medicineName = view.findViewById(R.id.medicine_name)
timeLayout = view.findViewById(R.id.time_layout)
medicineTime = view.findViewById(R.id.medicine_time)
}
}
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.layout_medicine_item, viewGroup, false)
return ViewHolder(view)
}
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
viewHolder.deleteLayout.setOnClickListener {
deleteRecord(viewHolder.adapterPosition)
}
viewHolder.medicineLayout.setOnClickListener {
val spinnerDialog = SpinnerDialog(activity, medicineSet.map { p -> p.name } as ArrayList<String>, "请选择药品", "关闭")
spinnerDialog.setCancellable(true)
spinnerDialog.setShowKeyboard(false)
spinnerDialog.bindOnSpinerListener { item, position ->
viewHolder.medicineName.text = item
}
spinnerDialog.showSpinerDialog()
}
}
override fun getItemCount(): Int {
return dataSet.count()
}
fun addRecord() {
val position = dataSet.count()
dataSet.add(position, MedicineModel())
notifyItemInserted(position)
}
#SuppressLint("NotifyDataSetChanged")
private fun deleteRecord(position: Int) {
dataSet.removeAt(position)
notifyItemRemoved(position)
notifyDataSetChanged()
}
I have called notifyDataSetChanged however it does not seems to work.
How should I initialize viewHolder? I have this error:
What I need to do is to get selected item in recyclerView but without using onClick method. When I get this selected item I need to show Toast message. Item is data class. Is it possible to pass some value from adapter to activity? Like I need to pass actual items from Data Class.
Process: com.pors.coopreaderlast, PID: 7862
kotlin.UninitializedPropertyAccessException: lateinit property viewHolder has not been initialized
at com.pors.coopreaderlast.features.polozka.PolozkaAdapter.getViewHolder(PolozkaAdapter.kt:18)
at com.pors.coopreaderlast.features.polozka.PolozkaAdapter.getCurrentItem(PolozkaAdapter.kt:46)
at com.pors.coopreaderlast.features.polozka.PolozkaActivity.onStart(PolozkaActivity.kt:213)
this is for line where viewHolder is set in Adapter:
lateinit var viewHolder: PolozkaViewHolder
This is Adapter
class PolozkaAdapter(val chosen_item: Int, private val listener: OnItemClickListener): ListAdapter<Polozka, PolozkaAdapter.PolozkaViewHolder>(DiffCallback()){
var selectedItemPosition: Int = chosen_item
lateinit var viewHolder: PolozkaViewHolder
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PolozkaViewHolder {
val binding = PolozkyItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
//return PolozkaViewHolder(binding)
viewHolder = PolozkaViewHolder(binding)
return viewHolder
}
override fun onBindViewHolder(holder: PolozkaViewHolder, position: Int) {
val currentItem = getItem(position)
holder.bind(currentItem)
if (selectedItemPosition == position){
holder.itemView.setBackgroundColor(Color.parseColor("#DA745A"))
} else
{
holder.itemView.setBackgroundColor(Color.TRANSPARENT)
}
}
fun getCurrentItem(): Polozka = super.getItem(viewHolder.bindingAdapterPosition)
override fun getItemId(position: Int): Long {
return super.getItemId(position)
}
override fun getItemCount(): Int {
return super.getItemCount()
}
inner class PolozkaViewHolder(private val binding: PolozkyItemBinding): RecyclerView.ViewHolder(binding.root){
init {
binding.root.setOnClickListener{
val position = bindingAdapterPosition
if (position != RecyclerView.NO_POSITION){
val item = getItem(position)
if (item != null){
listener.onItemClick(item, position)
}
}
notifyItemChanged(selectedItemPosition)
selectedItemPosition = bindingAdapterPosition
notifyItemChanged(selectedItemPosition)
}
}
fun bind(polozkaPolozka: Polozka){
binding.apply {
tvREG.text = polozkaPolozka.reg
tvVB.text = polozkaPolozka.veb.toString()
}
}
}
interface OnItemClickListener{
fun onItemClick(polozkaDoklad: Polozka, position: Int)
}
class DiffCallback: DiffUtil.ItemCallback<Polozka>(){
override fun areItemsTheSame(oldItem: Polozka, newItem: Polozka) =
oldItem.pvp06pk == newItem.pvp06pk
override fun areContentsTheSame(oldItem: Polozka, newItem: Polozka) =
oldItem == newItem
}
}
This is onCreate method but it can be in onCreate method also.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityPolozkaBinding.inflate(layoutInflater)
idPositionItem = intent.getIntExtra("positionItem",0)
val itemAdapter = PolozkaAdapter(idPositionItem, this)
binding.apply {
recyclerView.apply {
adapter = itemAdapter
layoutManager = LinearLayoutManager(this#ItemActivity)
}
itemViewModel.getall(index,idExp.toString() ).observe(this#PolozkaActivity){
itemAdapter.submitList(it)
}
}
val selectedItem = itemAdapter.getCurrentItem()
Toast.makeText(this, "Reg vybrane polozky je ${selectedItem.reg}", Toast.LENGTH_LONG).show()
I have similar question here: Similar question but here I use binding.
The reason you're getting this exception is that viewHolder has not been initalized at the moment you want to access it. And since it's a lateinit var, it expects to be initialized every time you access it. (see https://kotlinlang.org/docs/properties.html#late-initialized-properties-and-variables)
Instead of using a lateinit var for viewHolder, you can return the instance you created in the onCreateViewHolder() so no need to have an extra field in the adapter for it.
I believe you use viewHolder to find the selected item. In that case I suggest using a boolean (for instance you can name it selected) in your model object Polozka to indicate if the item is selected or not. And in you getCurrentItem() method I would write getCurrentList().find { it.selected } to find the currently selected item. In this case you need to update your list every time you select a new item and mark only that as selected.
class PolozkaAdapter(private val listener: OnItemClickListener): ListAdapter<Polozka, PolozkaAdapter.PolozkaViewHolder>(DiffCallback()){
lateinit var viewHolder: PolozkaViewHolder
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PolozkaViewHolder {
val binding = PolozkyItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return PolozkaViewHolder(binding)
}
override fun onBindViewHolder(holder: PolozkaViewHolder, position: Int) {
val currentItem = getItem(position)
holder.bind(currentItem)
if (currentItem.selected){
holder.itemView.setBackgroundColor(Color.parseColor("#DA745A"))
} else
{
holder.itemView.setBackgroundColor(Color.TRANSPARENT)
}
}
fun getCurrentItem(): Polozka = currentList.find { it.selected }
override fun getItemId(position: Int): Long {
return super.getItemId(position)
}
override fun getItemCount(): Int {
return super.getItemCount()
}
//Model object would look like
data class Polozka(
val selected: Boolean,
//rest of the fields
)
And in the observe you should do it like this.
itemViewModel.getall(index,idExp.toString() ).observe(this#PolozkaActivity){
// mark the item selected
val updatedList = it.mapIndexed { index, item ->
if (index == idPositionItem) {
item.copy(selected = true)
} else {
item
}
}
itemAdapter.submitList(updatedList)
}
}
val selectedItem = itemAdapter.getCurrentItem()
Toast.makeText(this, "Reg vybrane polozky je ${selectedItem.reg}", Toast.LENGTH_LONG).show()
And every time a new item gets selected you need to update your list.
I'm trying to pass my binding variable for the adapter to the ViewHolder to assing values to the textviews in my adapter but the values are not assigned and the click listeners dont do anything.
Here's my adapter class:
class DoneAppointmentsAdapter(var context: DoneAppointmentsFragment, listener: ContentListener, var arrayList: List<Appointment>) :
RecyclerView.Adapter<DoneAppointmentsAdapter.ItemHolder>() {
private val listener: ContentListener = listener
private var binding: DoneAppointmentsAdapterBinding? = null
var activity = context
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ItemHolder {
val viewHolder = LayoutInflater.from(parent.context)
.inflate(R.layout.done_appointments_adapter, parent, false)
binding = DoneAppointmentsAdapterBinding.inflate(LayoutInflater.from(parent.context))
return ItemHolder(viewHolder,binding, parent.context)
}
override fun onBindViewHolder(holder: ItemHolder, position: Int) {
holder.bind(arrayList, listener)
}
override fun getItemCount(): Int {
return arrayList.size
}
class ItemHolder(view: View, var binding: DoneAppointmentsAdapterBinding?, val context: Context) : RecyclerView.ViewHolder(view) {
fun bind(listOfData: List<Appointment>, listener: ContentListener) {
val dataListItem = listOfData[adapterPosition]
binding?.donePatientItemName?.text = "${dataListItem.patientName}"
binding?.donePatientItemTime?.text = "Some date"
binding?.donePatientItemPatientInfo?.setOnClickListener {
tempAppointmentId = dataListItem.id
listener.onPatientHistoryViewClicked(dataListItem.requestedBy)
}
binding?.donePatientItemReviewCase?.setOnClickListener {
amendPrescriptionWarning(dataListItem,context)
}
binding.donePatientItemViewCase.setOnClickListener {
startPreview(dataListItem)
}
}
}
}
You have messed up inside onCreateViewHolder . you have created view twice once with the LayoutInflater.from(parent.context) and once with DoneAppointmentsAdapterBinding.inflate . There should be only one in this case onlyDoneAppointmentsAdapterBinding .
class DoneAppointmentsAdapter(var context: DoneAppointmentsFragment, listener: ContentListener, var arrayList: List<Appointment>) :
RecyclerView.Adapter<DoneAppointmentsAdapter.ItemHolder>() {
private val listener: ContentListener = listener
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ItemHolder {
val binding = DoneAppointmentsAdapterBinding.inflate(LayoutInflater.from(parent.context))
return ItemHolder(binding)
}
override fun onBindViewHolder(holder: ItemHolder, position: Int) {
holder.bind(arrayList, listener)
}
override fun getItemCount(): Int {
return arrayList.size
}
class ItemHolder (var binding: DoneAppointmentsAdapterBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(listOfData: List<Appointment>, listener: ContentListener) {
val dataListItem = listOfData[adapterPosition]
binding.donePatientItemName.text = "${dataListItem.patientName}"
binding.donePatientItemTime.text = "Some date"
binding.donePatientItemPatientInfo.setOnClickListener {
tempAppointmentId = dataListItem.id
listener.onPatientHistoryViewClicked(dataListItem.requestedBy)
}
binding.donePatientItemReviewCase.setOnClickListener {
amendPrescriptionWarning(dataListItem,binding.donePatientItemReviewCase.context)
}
binding.donePatientItemViewCase.setOnClickListener {
startPreview(dataListItem)
}
}
}
}
It should be like this . I have also removed extra useless arguments from ItemHolder .
To make it clear the problem with your code was RecyclerView.ViewHolder(view) you were passing view while you were doing all action and stuff on binding those holds are two different instances of View . Which should be fixed with above code.
I have a nested recyclerview. Parent recyclerview adapter can add a data to child by a button, then child recyclerview adapter can remove a data in child by a button. The preview is like below.
Adding data seems fine, but when removing data i got index out of bound. I have called notifyDataSetChanged() in add or remove function.
My parent adapter code :
class FormPlanParentAdapter :
RecyclerView.Adapter<FormPlanParentAdapter.ViewHolder>() {
private val data: MutableList<MutableList<ItemPlan>> = mutableListOf()
private val viewPool = RecyclerView.RecycledViewPool()
fun setData(newData: List<MutableList<ItemPlan>>) {
data.clear()
data.addAll(newData)
notifyDataSetChanged()
}
fun getData(): String = Gson().toJson(data)
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ViewHolder {
return ViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.item_plan_parent, parent, false)
)
}
override fun getItemCount(): Int = data.size
override fun onBindViewHolder(
holder: ViewHolder,
position: Int
) {
val listPlans = data[position]
val childLayoutManager = LinearLayoutManager(
holder.recyclerView.context,
LinearLayoutManager.VERTICAL,
false
)
val childAdapter = FormPlanChildAdapter(listPlans, object : PlanParentCallback {
override fun deletePlan(position: Int) {
listPlans.removeAt(position)
notifyDataSetChanged()
}
})
holder.recyclerView.apply {
layoutManager = childLayoutManager
adapter = childAdapter
setRecycledViewPool(viewPool)
}
holder.textView.text = "Hari ke ${position + 1}"
holder.imageButton.setOnClickListener {
listPlans.add(ItemPlan())
notifyDataSetChanged()
}
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val recyclerView: RecyclerView = itemView.rv_plan_child
val textView: TextView = itemView.tv_days_of
val imageButton: ImageButton = itemView.ib_add
}
interface PlanParentCallback {
fun deletePlan(position: Int)
}
}
My child adapter code :
class FormPlanChildAdapter(
private val listPlans: List<ItemPlan>,
private val callback: FormPlanParentAdapter.PlanParentCallback
) :
RecyclerView.Adapter<FormPlanChildAdapter.ViewHolder>() {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ViewHolder {
return ViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.item_plan_child, parent, false)
)
}
override fun getItemCount(): Int = listPlans.size
override fun onBindViewHolder(
holder: ViewHolder,
position: Int
) {
val itemPlan = listPlans[position]
holder.etPlan.setText(itemPlan.plan)
holder.etPlan.doAfterTextChanged {
listPlans[position].plan = it.toString()
}
if (position == 0) {
holder.ibDelete.invisible()
} else {
holder.ibDelete.visible()
}
holder.ibDelete.setOnClickListener {
if (listPlans.size > 1) {
callback.deletePlan(position)
}
}
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val etPlan: EditText = itemView.et_plan
val ibDelete: ImageButton = itemView.ib_delete
}
}
Any help appreciated, thank you.
Reason:
The old TextWatchers and adapter position mess up when the dataset changed.
notifyDatasetChanged triggers onBindViewHolder, and then EditText's TextWatcher is being notified because of this line
holder.etPlan.setText(itemPlan.plan)
Since etPlan has already an active TextWatcher from previous binding, it tries to notify it with the old position of the adapter.
Quick answer:
Keep the TextWatcher in your ViewHolder, remove it from EditText on onBindViewHolder, and set it to the EditText again after setting the EditText's value.
So, update your child adapter's onBindViewHolder as
override fun onBindViewHolder(
holder: ViewHolder,
position: Int
) {
val itemPlan = listPlans[position]
holder.etPlan.removeTextChangedListener(holder.textWatcher)
holder.etPlan.setText(itemPlan.plan)
holder.textWatcher = holder.etPlan.doAfterTextChanged {
listPlans[position].plan = it.toString()
}
...
}
and also update it's ViewHolder like:
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val etPlan: EditText = itemView.et_plan
val ibDelete: ImageButton = itemView.ib_delete
var textWatcher: TextWatcher? = null
}
But, it's not recommended setting listeners on onBindViewHolder due to performance concerns. Please check this and this.
Here is another workaround:
Move all the TextWatcher things to Adapter via a listener, and prevent notifying the TextWatcher if it's not necessary.
interface TextChangeListener {
fun onTextChange(text: String, position: Int)
}
class FormPlanChildAdapter(...) :
RecyclerView.Adapter<FormPlanChildAdapter.ViewHolder>(), TextChangeListener {
override fun onBindViewHolder(
holder: ViewHolder,
position: Int
) {
val itemPlan = listPlans[position]
holder.setPlan(itemPlan.plan)
...
}
override fun onTextChanged(text: String, position: Int) {
listPlans[position].plan = text
}
inner class ViewHolder(itemView: View, textChangeListener: TextChangeListener) :
RecyclerView.ViewHolder(itemView) {
private var disableTextChangeListener = false
private val etPlan: EditText = itemView.et_plan
val ibDelete: ImageButton = itemView.ib_delete
init {
etPlan.doAfterTextChanged {
if (!disableTextChangeListener) {
textChangeListener.onTextChanged(it.toString(), adapterPosition)
}
}
}
fun setPlan(plan: String, notifyTextChangeListener: Boolean = false) {
if (notifyTextChangeListener) {
etPlan.setText(plan)
} else {
disableTextChangeListener = true
etPlan.setText(plan)
disableTextChangeListener = false
}
}
}
}
Please try doing
listPlans.removeAt(position)
notifyItemRemoved(position)
instead of
listPlans.removeAt(position)
notifyDataSetChanged()
I have simple RecyclerViewAdapter class:
class TariffsCardAdapter(context: Context, tariffCardItems: List<ItemsItem?>?) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var context: Context? = null
private var tariffCardItems: ArrayList<ItemsItem?>? = null
init {
this.context=context
this.tariffCardItems=tariffCardItems as ArrayList<ItemsItem?>
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_tariff_card_items, parent, false)
return TariffsCardAdapterViewHolder(view)
}
override fun getItemCount(): Int {
return tariffCardItems!!.size
}//getItemCount ends
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val viewHolder = holder as TariffsCardAdapterViewHolder
Log.e("posX","pos:::".plus(position))
}
private inner class TariffsCardAdapterViewHolder : RecyclerView.ViewHolder {
var text: TextView? = null
constructor(row: View) : super(row) {
text= row.findViewById(R.id.text) as TextView
}
}
}
Now lets suppose that my tariffCardItems: List<ItemsItem?> will have only 5 items in the list that I want to show.
The problem is that when the adapter gets instantiated that is for the first time the onBindViewHolder method is called twice.
So that the Log values prints as:
pos:::0
pos:::1
pos:::0
pos:::1
Which means that my recycler view position will be 1 in the end.
And the very first view will be created with list item at index 1 which is wrong and should be `0.
In other words, the very first child of the recycler view is created by 1 position value which is wrong.
What am I doing wrong?
It's simply because you are calling adapter 2 in code an recyclerview's bindviewholder should use to bind data not to call viewholder.
class TariffsCardAdapter(context: Context, tariffCardItems: List<ItemsItem?>?) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var context: Context? = null
private var tariffCardItems: ArrayList<ItemsItem?>? = null
init {
this.context=context
this.tariffCardItems=tariffCardItems as ArrayList<ItemsItem?>
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_tariff_card_items, parent, false)
return TariffsCardAdapterViewHolder(view)
}
override fun getItemCount(): Int {
return tariffCardItems!!.size
}//getItemCount ends
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
//bind data
}
private inner class TariffsCardAdapterViewHolder : RecyclerView.ViewHolder {
var text: TextView? = null
constructor(row: View) : super(row) {
text= row.findViewById(R.id.text) as TextView
}
}
}
For example your adapter should be like this
class CustomAdapter(val userList: ArrayList<User>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
//this method is returning the view for each item in the list
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.list_layout, parent, false)
return ViewHolder(v)
}
//this method is binding the data on the list
override fun onBindViewHolder(holder: CustomAdapter.ViewHolder, position: Int) {
holder.bindItems(userList[position])
}
//this method is giving the size of the list
override fun getItemCount(): Int {
return userList.size
}
//the class is hodling the list view
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bindItems(user: User) {
val textViewName = itemView.findViewById(R.id.textViewUsername) as TextView
val textViewAddress = itemView.findViewById(R.id.textViewAddress) as TextView
textViewName.text = user.name
textViewAddress.text = user.address
}
}
}
This method from your code is calling twice
val viewHolder = holder as TariffsCardAdapterViewHolder
Log.e("posX","pos:::".plus(position))