skip to Main Content

I get error when I press button inside recycler view. My application is not crashing. I am trying to set a button in the recycler view and callingsetOnClickListener inside onBindViewHolder. Inside the holder.Button.setOnClickListener{}I change the button text to notified. But when I press a button the values of other button text in another list also changes. This is a listview of firestore documents. I have many documents that are uploaded into the recycler view. If I am getting the error how should I implement the button onclicklistener without this error.[![https://i.stack.imgur.com/S0Oxm.jpg][1]][1] [![enter image description here][2]][2]


/**This my activity for recycler view*/

package com.example.bloodbankcompany.recyclerview

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Adapter
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.bloodbankcompany.MyAdapter
import com.example.bloodbankcompany.R
import com.example.bloodbankcompany.User1
import com.example.bloodbankcompany.User2
import com.google.firebase.firestore.*
import java.lang.NullPointerException

class MainActivity2 : AppCompatActivity() {

    private lateinit var recyclerView: RecyclerView
    private lateinit var userArrayList: ArrayList<User2>
    private lateinit var myAdapter: MyAdapter2
    private val mFireStore = FirebaseFirestore.getInstance()

    var db = FirebaseFirestore.getInstance()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)

        recyclerView= findViewById(R.id.recyclerview)
        recyclerView.layoutManager = LinearLayoutManager(this)

        recyclerView.setHasFixedSize(true)
        userArrayList= arrayListOf()
        myAdapter =MyAdapter2(userArrayList)


        recyclerView.adapter = myAdapter

        EventChangeListener()



    }



    private fun EventChangeListener() {
         try {
             mFireStore.collection("applicationForm").addSnapshotListener(object :
                 EventListener<QuerySnapshot> {
                 override fun onEvent(value: QuerySnapshot?, error: FirebaseFirestoreException?) {
                     if (error != null) {
                         Log.e("firestore error", error.message.toString())
                     }
                 try {
                     for (dc: DocumentChange in value?.documentChanges!!) {
                         if (dc.type == DocumentChange.Type.ADDED) {
                             userArrayList.add(dc.document.toObject(User2::class.java))
                         }
//                    Toast.makeText(applicationContext,userArrayList.toString(), Toast.LENGTH_SHORT).show()

                     }
                 } catch (e:NullPointerException){

                 }
                     myAdapter.notifyDataSetChanged()
                 }

             })
         } catch (e:NullPointerException){

         }


    }


}



/**
* This is my myAdapter  activity for adapater*/


 package com.example.bloodbankcompany.recyclerview


import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.example.bloodbankcompany.R
import com.example.bloodbankcompany.RegisterActivity
import com.example.bloodbankcompany.User2
import com.google.firebase.firestore.FirebaseFirestore
import kotlinx.android.synthetic.main.list_item2.view.*

class MyAdapter2(private val userList: ArrayList<User2>): RecyclerView.Adapter<MyAdapter2.MyViewHolder>(){
var id: String = ""
    private val mFireStore = FirebaseFirestore.getInstance()


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyAdapter2.MyViewHolder {
        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.list_item2,parent,false)
        return MyViewHolder(itemView)



    }

  

    override fun onBindViewHolder(holder: MyAdapter2.MyViewHolder, position: Int) {

        val user:User2 = userList[position]
        holder.name.text= user.name
        holder.phone.text= user.phone
        holder.address.text =user.address
        holder.bloodGroup.text= user.bloodgroup
        holder.id.text = user.id

//Setting onclicklistener to my adapter and starting intent
        holder.button.setOnClickListener {
//            holder.io = "kkj"
//            holder.id.text = " "
            holder.button.setText("notified")


//            val context=holder.button.context
//            val intent = Intent( context, RegisterActivity::class.java)
//            context.startActivity(intent)
        }

    }

    override fun getItemCount(): Int {
        return userList.size

    }

    public class MyViewHolder(itemView : View): RecyclerView.ViewHolder(itemView){




        val name : TextView = itemView.findViewById(R.id.tvfirstname1)
        val phone :TextView= itemView.findViewById(R.id.tvphone11)
        val address : TextView= itemView.findViewById(R.id.tvaddress1)
        val bloodGroup: TextView =itemView.findViewById(R.id.tvbloodg1)
        val id: TextView = itemView.findViewById(R.id.tvid)
        var io: String? = ""
        var button: Button = itemView.findViewById(R.id.btn_notify)

        class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
            init {
                itemView.btn_notify.setOnClickListener {

                }
            }


        }




    }
} ```


  [1]: https://i.stack.imgur.com/S0Oxm.jpg
  [2]: https://i.stack.imgur.com/BqDMf.jpg

2

Answers


  1. create interface for clickListener in your adapter and set it in constructor

    interface OnItemClickListener {
    fun onItemClick(position: Int)
    }
    

    and in ViewHolder set bind your button

    fun bind(position: Int, listener: OnItemClickListener) {
    button.setOnClickListener { v -> listener.onItemClick(position) }
    }
    

    and then set this code in onBindViewHolder

    holder.bind( position , onItemClickListener)
    

    finally when click on button you can action in Activity or Fragment

    example :

    adapter = Adapter(getContext(), models) { position -> }
    
    Login or Signup to reply.
  2. Simple Code, Without using Interface

    Actually what I found is you were doing it the correct way, but you were using two ViewHolder classes there which is the cause of issue. Try to use the below code once and try again. Hope it works.

    class mAdapter(val context: Context, private val dataList: ArrayList<String>):
        RecyclerView.Adapter<mAdapter.ViewHolder>() {
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): mAdapter.ViewHolder {
            val v = LayoutInflater.from(parent.context).inflate(R.layout.item_card_view, parent, false)
            return mAdapter.ViewHolder(v)
        }
    
        override fun onBindViewHolder(holder: mAdapter.ViewHolder, position: Int) {
            holder.txtView.setText(dataList.get(position))
            
            //Your Button setOnClickLister
            holder.btnName.setOnClickListener {
                
                // action here
            
            }
    
        }
    
        override fun getItemCount(): Int {
            return dataList.size
        }
    
        class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    
           
            val txtView  = itemView.findViewById(R.id.textView) as TextView
            val btnName = itemView.findViewById(R.id.btnName) as Button
    
        }
    
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search