简体   繁体   English

如何为回收器适配器提供点击监听接口的实现?

[英]How to provide an implementation of the click listener interface for the recycler adapter?

Suppose we have a recycler view in a fragment, and we need to add a click handler to the adapter.假设我们在片段中有一个回收器视图,我们需要向适配器添加一个点击处理程序。 Which one of the following approaches are better?以下哪种方法更好? Please tell me the pros and cons each one:请告诉我每一种的优缺点:

Approach One: implementing OnItemClickListener in the fragment:方法一:在片段中实现 OnItemClickListener:

In this approach we implement the OnItemClickListener in the fragment class MyFragment: Fragment(), MyAdapter.OnItemClickListener and pass it to the adapter using this keyword:在这种方法中,我们在片段class MyFragment: Fragment(), MyAdapter.OnItemClickListener中实现 OnItemClickListener 并使用this关键字将其传递给适配器:

class MyFragment : Fragment() , MyAdapter.OnItemClickListener {

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
        // Inflate the layout for this fragment
        myRecyclerView.adapter = MyAdapter(it , this) // here we pass the fragment 
    
        return view
    }

    override fun onCLick(item: MyItem) {
        Log.d("test","item name = " + item.Name)
    }
}

class MyAdapter(val data: List<MyItem> , val onItemClickListener: OnItemClickListener) :
RecyclerView.Adapter<MyFragment.MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.support_simple_spinner_dropdown_item, parent, false)
        return MyViewHolder(view)
    }

    override fun getItemCount() = data.size

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        holder.itemView.setOnClickListener{
            onItemClickListener.onCLick(data[position])
        }
        with(holder) {
            textView1?.let {
                it.text = data[position].Name
            }
        }
    }

    interface OnItemClickListener{
        fun onCLick(item: MyItem)
    }
}

Approach Two: implementing OnItemClickListener using a anonymous object:方法二:使用匿名 object 实现 OnItemClickListener:

In this approach we use object: syntax to create an anonymous object, like inline interface implementation in java:在这种方法中,我们使用object:语法来创建匿名 object,就像 java 中的内联接口实现一样:

class MyFragment : Fragment(){
override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        myRecyclerView.adapter = MyAdapter(it ,object : MyAdapter.OnItemClickListener{
            override fun onCLick(item: MyItem) {
                Log.d("test","name = " + item.Name)
            }
        })
        return view
    }

class MyAdapter(val data: List<MyItem> , val onItemClickListener: OnItemClickListener) :
    RecyclerView.Adapter<MyViewHolder>() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.support_simple_spinner_dropdown_item, parent, false)
        return MyViewHolder(view)
    }

    override fun getItemCount() = data.size

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        holder.itemView.setOnClickListener{
            onItemClickListener.onCLick(data[position])
        }
        with(holder) {
            textView1?.let {
                it.text = data[position].Name
            }
        }
    }

    interface OnItemClickListener{
        fun onCLick(item: MyItem)
    }
}
  1. Which one is more modern?哪个更现代?
  2. Which one gives a better performance?哪一个提供更好的性能? (If there is any difference) (如果有任何区别)
  3. Why in most tutorials and video lessons they use the first approach, while the second one needs fewer lines of codes?为什么在大多数教程和视频课程中他们使用第一种方法,而第二种方法需要更少的代码行?

Simple answer: it doesn't matter.简单的回答:没关系。 Approach 2 simply allocates one extra object on the heap which is not a big deal.方法 2 只是在堆上分配一个额外的 object,这没什么大不了的。 I would prefer 2 over 1 because 1 exposes that MyFragment implements MyAdapter.OnItemClickListener : that should remain an implementation detail, not a part of your fragment's contract.我更喜欢 2 而不是 1,因为 1 公开了MyFragment实现MyAdapter.OnItemClickListener :这应该是实现细节,而不是片段合同的一部分。

However, there is something in your code that can affect performance.但是,您的代码中有些东西会影响性能。 Your setOnClickListener() call allocates new listener whenever onBindViewHolder() is called, which is pretty often if you scroll fast enough.每当调用onBindViewHolder() () 时,您的setOnClickListener()调用都会分配新的侦听器,如果您滚动得足够快,这通常会发生。 It adds to the work of your garbage collector.它增加了垃圾收集器的工作。

You can always get ViewHolder 's position in adapter with getBindingAdapterPosition() (or its deprecated counterpart getAdapterPosition() if you're using an older version of RecyclerView).您始终可以使用getBindingAdapterPosition() (如果您使用的是旧版本的 RecyclerView 则使用其已弃用的对应物getAdapterPosition())在适配器中获取ViewHolder的 position。 As you can see from the docs, in marginal cases it may not be consistent with the position you use and is a more correct approach to handling user actions.正如您从文档中看到的那样,在边缘情况下,它可能与您使用的position不一致,并且是处理用户操作的更正确方法。

With that said, it is sufficient to set your listener only once, in onCreateViewHolder() :话虽如此,只需在onCreateViewHolder()中设置一次监听器就足够了:

override fun onCreateViewHolder(
    parent: ViewGroup,
    viewType: Int
): MyViewHolder {
    val view = LayoutInflater.from(parent.context)
        .inflate(R.layout.support_simple_spinner_dropdown_item, parent, false)
    val holder = MyViewHolder(view)

    holder.itemView.setOnClickListener {
        holder
            .bindingAdapterPosition
            .takeUnless { it == RecyclerView.NO_POSITION }
            ?.let { position ->
                onItemClickListener.onClick(data[position])
            }
    }

    return holder
}

Here you can use Callback , it is the recommended choice of Google's Android team.在这里你可以使用Callback ,它是 Google 的 Android 团队的推荐选择。 You implement that as:您将其实现为:


class MyFragment : Fragment(){
override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        myRecyclerView.adapter = MyAdapter(it) { item ->

           // You can use your item here.

        }
        return view
    }

class MyAdapter(val data: List<MyItem> ,
               private val callback: (MyItem) -> Unit) :
    RecyclerView.Adapter<MyViewHolder>() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.support_simple_spinner_dropdown_item, parent, false)
        return MyViewHolder(view)
    }

    override fun getItemCount() = data.size

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        holder.itemView.setOnClickListener{
            callback.invoke(data[position])
        }
        with(holder) {
            textView1?.let {
                it.text = data[position].Name
            }
        }
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 Adapter 中的 Kotlin 中提供长按监听器 - How to provide long click listener in Kotlin in Adapter 如何在回收器适配器中初始化侦听器? - How do I initialize a listener in a recycler adapter? 将侦听器传递给回收器适配器 - Passing a listener to a recycler adapter 如何将子点击监听器添加到任何子项目 manneohlund smart-recycler-adapter - How to add child click listener to any child item manneohlund smart-recycler-adapter Recycler视图单击Listener - Recycler view Click Listener Android:在“项目”上单击“侦听器”以实现列表视图基本适配器实现 - Android: On Item Click Listener for List View Base Adapter implementation android:如何在回收器视图和适配器clss之间建立接口 - android: how to make interface between recycler view and adapter clss 如何为列表视图适配器中的开关添加点击监听器 - how to add click listener for a switch in listview adapter 如何从Recycler-View适配器接收活动中的点击事件 - How to receive click event in activity from a recycler-view adapter 使用适配器和数组列表时,我需要在回收视图中的项目上实现单击侦听器 class - I need to implementation click listener class on item in recycle view when using adapter and array list
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM