Implementing click listener for RecyclerView adapter correctly

问题: What's the correct way to create a click listener for an item in a RecyclerView adapter? This tutorial says it should be done in onBindViewHolder but others have said in on...

问题:

What's the correct way to create a click listener for an item in a RecyclerView adapter? This tutorial says it should be done in onBindViewHolder but others have said in onCreateViewHolder and I've not seen any tutorials for the latter hence I'm perplexed.

class MyRVAdapter(private val myList: ArrayList<Item>) : RecyclerView.Adapter<MyRVAdapter.ViewHolder>() {
    override fun getItemCount(): Int {
        return myList.size
    }

    class ViewHolder (itemView : View):RecyclerView.ViewHolder(itemView) {
        // val myButton = itemView.findViewById<Button>(R.id.btn_A)!!
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.myButton.text = (myList[position].btnTitle)
     }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val v = LayoutInflater.from(parent.context).inflate(R.layout.my_cv, parent, false)
        return ViewHolder(v)

        val myButton = v.findViewById<Button>(R.id.btn_A)!!

        myButton.setOnClickListener {
            customView = View.inflate(holder.itemView.context, R.layout.fragment_dialog, null)

                val builder = AlertDialog.Builder(holder.itemView.context)
                builder.setIconAttribute(R.attr.imgInfo)
                builder.setTitle(R.string.dialog_title)
                builder.setView(customView)
                builder.setPositiveButton(android.R.string.ok){ dialog, _ -> dialog.dismiss() }
                builder.show()
        }
    }
}

回答1:

In Kotlin

In Kotlin you cant implement onClickListener in ViewHolderClass directly. In Kotlin to achieve the same, you have to do onClickListener inside onBindViewHolder

holder.myButton.setOnClickListener {
            //do your stuff here
}

or use init function

// I'm not sure this is a correct method or not

class MyRVAdapter : RecyclerView.Adapter<MyRVAdapter.ViewHolder>() {


    override fun getItemCount(): Int {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }


    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyRVAdapter.ViewHolder {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
        var myButton = itemView.findViewById(R.id.button) as Button

         // use any of the following declaratons
         // val myButton = itemView.findViewById(R.id.button) as Button
         // val myButton = itemView.findViewById<Button>(R.id.button)
         // var myButton = itemView.findViewById<Button>(R.id.button)
         // var myButton:Button = itemView.findViewById(R.id.button)
         // val myButton:Button = itemView.findViewById(R.id.button)


        // to avoid Expecting Member Declaration is showing in kotlin  use constructor
       // Expecting Member Declaration is showing because kotlin allows null declaration so a constructor or init is required to avoid this
        init {
            myButton.setOnClickListener{
                //do your stuff here
            }
        }

    }
}

In Java

onBindViewHolder will be executed whenever there is a change in data. So it is good to write the onClickListener in The ViewHolderClass.

myButton.setOnClickListener {
            //do your stuff here
}

回答2:

The correct way is to make it work in its simplest form.
Can you assign the listener "ahead" from onCreateViewHolder, and if so why wouldn't you?
Consider the fact that onBindViewHolder will get repeatedly executed.
Unless you obtain new data affecting your view after the viewholder creation, there should be no reason to change your listener "during the execution" from recurrent onBindViewHolder calls.


回答3:

onBindViewHolder() will be called all the time when your Views appear on the screen so it is called more that your items' count. You will create lots of duplicate listeners when you scroll. Setting listener in ViewHolder will create one listener per holder. Here is the code:

class MyRVAdapter() : RecyclerView.Adapter<MyRVAdapter.ViewHolder>() {

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.myButton.text = "set here all except listener"
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val v = LayoutInflater.from(parent.context).inflate(R.layout.my_cv, parent, false)
        return ViewHolder(v)
    }

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

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

        var myButton: Button = itemView.findViewById(R.id.btn_A)

        init {
            myButton.setOnClickListener {
                val customView = View.inflate(itemView.context, R.layout.fragment_dialog, null)

                val builder = AlertDialog.Builder(itemView.context)
                builder.setIconAttribute(R.attr.imgNight)
                builder.setTitle(R.string.dialog_title)
                builder.setView(customView)
                builder.setPositiveButton(android.R.string.ok){ dialog, _ -> dialog.dismiss() }
                builder.show()

                val tabLayout = customView.findViewById(R.id.mTabLayout)
                val viewPager = customView.findViewById(R.id.mViewPager)

                val adapter = TabbedDialogAdapter(childFragmentManager)//i dont understand how you get this but it is another question
                adapter.addFragment("Tab A", TabbedDialogFragment.createInstance("Description A"))
                adapter.addFragment("Tab B", TabbedDialogFragment.createInstance("Description B"))
                adapter.addFragment("Tab C", TabbedDialogFragment.createInstance("Description C"))

                viewPager.adapter = adapter
                tabLayout.setupWithViewPager(viewPager)
            }
        }
    }
}
  • 发表于 2019-03-03 04:30
  • 阅读 ( 232 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除