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?
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.
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.
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 .
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With