I was exploring RecyclerView
and I was surprised to see that RecyclerView
does not have onItemClickListener()
. Because RecyclerView
extends
android.view.ViewGroup
and ListView
extends
android.widget.AbsListView
. However I solved my problem by writing onClick
in my RecyclerView.Adapter
:
public static class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
public TextView txtViewTitle;
public ImageView imgViewIcon;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.item_title);
imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.item_icon);
}
@Override
public void onClick(View v) {
}
}
But still I want to know why Google removed onItemClickListener()
?
Is there a performance issue or something else?
tl;dr 2016 Use RxJava and a PublishSubject to expose an Observable for the clicks.
Original Post:
Since the introduction of
ListView
,onItemClickListener
has been problematic. The moment you have a click listener for any of the internal elements the callback would not be triggered but it wasn't notified or well documented (if at all) so there was a lot of confusion and SO questions about it.Given that
RecyclerView
takes it a step further and doesn't have a concept of a row/column, but rather an arbitrarily laid out amount of children, they have delegated the onClick to each one of them, or to programmer implementation.Think of
Recyclerview
not as aListView
1:1 replacement but rather as a more flexible component for complex use cases. And as you say, your solution is what google expected of you. Now you have an adapter who can delegate onClick to an interface passed on the constructor, which is the correct pattern for bothListView
andRecyclerview
.and then on your adapter
Now look into that last piece of code:
onCreateViewHolder(ViewGroup parent, int viewType)
the signature already suggest different view types. For each one of them you'll require a different viewholder too, and subsequently each one of them can have a different set of clicks. Or you can just create a generic viewholder that takes any view and oneonClickListener
and applies accordingly. Or delegate up one level to the orchestrator so several fragments/activities have the same list with different click behaviour. Again, all flexibility is on your side.It is a really needed component and fairly close to what our internal implementations and improvements to
ListView
were until now. It's good that Google finally acknowledges it.Following up MLProgrammer-CiM's excellent RxJava solution
Consume / Observe clicks
RxJava 2.+
Modify the original tl;dr as:
PublishSubject#asObservable()
was removed. Just return thePublishSubject
which is anObservable
.I use this method to start an Intent from RecyclerView:
RecyclerView doesn't have an
onItemClickListener
because RecyclerView is responsible for recycling views (surprise!), so it's the responsibility of the view that is recycled to handle the click events it receives.This actually makes it much easier to use, especially if you had items that can be clicked in multiple places.
Anyways, detecting click on a RecyclerView item is very easy. All you need to do is define an interface (if you're not using Kotlin, in which case you just pass in a lambda):
Same code in Kotlin:
Yes you can
use PlaceHolderView