28

I am using RecyclerViews in my app project and setting OnClickListeners with their ViewHolders (in their constructors like mentioned in a StackOverflow Q&A).

Then I have this question: how can I remove OnClickListeners from RecyclerView's ViewHolders when they are disposed.

Usually, we can remove an OnClickListener by doing this:

view.setOnClickListener(null);

And if it is a ViewPager's PagerAdapter, we can do so in destroyItem method.

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    View view = container.findViewById(R.id.viewId);
    view.setOnClickListener(null);
}

Where can I do so with RecyclerView? --Or, I need not do so?

Community
  • 1
  • 1
hata
  • 11,633
  • 6
  • 46
  • 69
  • 1
    I don't think you need to set the click listener to null. The callback should be picked up by the garbage collector when the view is disposed. Also, if we were expected to do so, I would have expected a removeOnClicklistener method to be present. – cYrixmorten Nov 21 '15 at 17:58

2 Answers2

28

If you want to null set the onCLickListener() of the views of RecyclerView.Adapter when the view goes off the screen, you can do so by overriding the http://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#onViewDetachedFromWindow(VH) in your recyclerView's adapter. You will receive the holder as parameter that has just gone off the screen. You can null set onClickListener of any view available in that holder.

Or if you just want to do the same when it becomes visible on the screen, you can do in onBindViewHolder(). But this does not make sense as instead you can avoid setting listener.

Points to remember, related to this answer:
Setting the listener to null may be ther requirement when you do not want to set click listener to view for every data set but to only few. In this case, it is always better to set listenrs to null as and when they go off the screen. Otherwise, as RecyclerView will re-use (recycle) the holder objects that were gone away to represent the new dataset that is becoming visible. In this process, data set (view in a holder) that you did not set the listener to may have the listener set because of recycling.

All in all, while getting the advantage of smooth scrolling due to recycling, it is dev's responsibility to reset the views (clearing image views, text views etc..) and null setting the onCLickListener etc.

cgr
  • 4,578
  • 2
  • 28
  • 52
  • I tried deleting the viewholders as observers when the onViewDetachedFromWindow(VH) was called. But I observed one misbehavior, the callback was being fired for the extreme items on the screen, even when they were visible. So, I used onViewRecycled(VH) instead. – h8pathak Aug 15 '20 at 08:04
  • 1
    Are you sure the correct pair to use is `onViewDetachedFromWindow` <-> `onBindViewHolder`?. If the view is detached from the window that doesn't necessarily mean it is "disposed". Correct pair should be onViewRecycled` <-> `onBindViewHolder` as described on developer's page (https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#onviewrecycled) – Farid Jun 07 '21 at 13:34
2

If you are using RecyclerView and binding OnClickListeners to it's every row root view, there is no need to dispose them.

But if some views shouldn't respond to click event's just use setOnClickListener(null)

michal.luszczuk
  • 2,883
  • 1
  • 15
  • 22