Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is adding an OnClickListener inside onBindViewHolder of a RecyclerView.Adapter considered bad practice?

I have the following code for a RecyclerView.Adapter class and it works fine:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.Viewholder> {      private List<Information> items;     private int itemLayout;      public MyAdapter(List<Information> items, int itemLayout){         this.items = items;         this.itemLayout = itemLayout;     }      @Override     public Viewholder onCreateViewHolder(ViewGroup parent, int viewType) {         View v = LayoutInflater.from(parent.getContext()).inflate(itemLayout, parent, false);         return new Viewholder(v);     }      @Override     public void onBindViewHolder(Viewholder holder, final int position) {         Information item = items.get(position);         holder.textView1.setText(item.Title);         holder.textView2.setText(item.Date);          holder.itemView.setOnClickListener(new View.OnClickListener() {             @Override             public void onClick(View view) {                 Toast.makeText(view.getContext(), "Recycle Click" + position, Toast.LENGTH_SHORT).show();             }         });         holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {        @Override        public boolean onLongClick(View v) {           Toast.makeText(v.getContext(), "Recycle Click" + position, Toast.LENGTH_SHORT).show();            return true;        } });     }      @Override     public int getItemCount() {         return items.size();     }      public class Viewholder extends RecyclerView.ViewHolder {         public  TextView textView1;         public TextView textView2;          public Viewholder(View itemView) {             super(itemView);             textView1=(TextView) itemView.findViewById(R.id.text1);             textView2 = (TextView) itemView.findViewById(R.id.date_row);          }     } } 

However, I believe it is bad practice to implement the OnClickListener in the onBindViewHolder method. Why is this bad practice, and what is a better alternative?

like image 249
Sujit Yadav Avatar asked Nov 21 '15 16:11

Sujit Yadav


People also ask

What is the difference between onCreateViewHolder and onBindViewHolder?

When used, pass the child Class Object, and in onCreateViewHolder , use Reflection to create the child ViewHolder. When you get an onBindViewHolder, just pass it to the ViewHolder.

What is the use of onBindViewHolder?

bindViewHolder. This method internally calls onBindViewHolder(ViewHolder, int) to update the RecyclerView. ViewHolder contents with the item at the given position and also sets up some private fields to be used by RecyclerView.

What is onCreateViewHolder?

onCreateViewHolder only creates a new view holder when there are no existing view holders which the RecyclerView can reuse. So, for instance, if your RecyclerView can display 5 items at a time, it will create 5-6 ViewHolders , and then automatically reuse them, each time calling onBindViewHolder .


1 Answers

The reason it is better to handle your click logic inside the ViewHolder is because it allows for more explicit click listeners. As expressed in the Commonsware book:

Clickable widgets, like a RatingBar, in a ListView row had long been in conflict with click events on rows themselves. Getting rows that can be clicked, with row contents that can also be clicked, gets a bit tricky at times. With RecyclerView, you are in more explicit control over how this sort of thing gets handled… because you are the one setting up all of the on-click handling logic.

By using the ViewHolder model you can gain a lot of benefits for click handling in a RecyclerView than previously in the ListView. I wrote about this in a blog post comparing the differences - https://androidessence.com/recyclerview-vs-listview

As for why it is better in the ViewHolder instead of in onBindViewHolder(), that is because onBindViewHolder() is called for each and every item and setting the click listener is an unnecessary option to repeat when you can call it once in your ViewHolder constructor. Then, if your click responds depends on the position of the item clicked, you can simply call getAdapterPosition() from within the ViewHolder. Here is another answer I've given that demonstrates how you can use the OnClickListener from within your ViewHolder class.

like image 71
AdamMc331 Avatar answered Oct 21 '22 01:10

AdamMc331