1

Edited:

I want know about creating Anonymous Listener in bindViewHolder method cause any performance problem or not for large data set.

Suppose i have a RecyclerView Adapter. And in bindViewHolder method if i set all my listeners Anonymously does this cause any performance problem? Because when user scrolls the RecyclerView it will create lots of Anonymous listeners and set them to the views.

Example:

view.setOnClickListener(new View.OnClickListener()
{
    @Override
    public void onClick(View v)
    {
    } 
});

Or i can implements OnClickListener in my ViewHolder class and just add to views.Like

view.setOnClickListener(this);

Here lots of Anonymous Listeners are not created. Does this perform better from previous in performance calculation for large dataset?

Thanks in advance.

Abu Yousuf
  • 5,729
  • 3
  • 31
  • 50
  • Can u try this inside viewholder create listener and there is one property this.setIsRecyclable(false) which will make performance better can try this one https://stackoverflow.com/questions/46095866/getting-android-recyclerview-to-update-view-inside-react-native-component/46313257#46313257 – Amjad Khan Sep 30 '17 at 17:21

3 Answers3

1

RecyclerView will only display few items, ViewHolder will only be created for items that are visible, so even if you have 1000s of items in your adapter, only small fraction of ViewHolders are created.

But you will have to be careful with addListener methods, for most setListener methods, you will be setting same listener again and again when item is recycled, which does not take less then few milliseconds as it only keeps reference of the listener implementation.

But with addListener, you will have to remove old listener before adding new one.

Example of setListener is setClickListener and example of addListener is addTextWatcher

//.. part of adapter

private TextWatcher textWatcher;

public void bindViewHolder(DataViewHolder holder, int index){

    // no performance issue
    holder.button.setClickListener( .... );

    // wrong, this is added everytime
    holder.editText.addTextWatcher( .... );


    // this is safe...
    if(textWatcher != null)
       holder.editText.removeTextWatcher(textWatcher);

    textWatcher = new TextWatcher(){
       // ... implementation
    };
    holder.editText.addTextWatcher(textWatcher);
}
Akash Kava
  • 39,066
  • 20
  • 121
  • 167
  • 1
    Thanks for your answer. Actually i was focused on setting listeners anonymously.( I have edited my question. Sorry for that.) I think every time i set anonymous listeners in `bindViewHolder` method i will create new anonymous class.So there will be lots of Anonymous class created when scrolling. Correct me if i am wrong. Thanks – Abu Yousuf Oct 01 '17 at 04:44
0

Basically, you set a OnClickListener in every item of your RecyclerView and "connect" it to your Activity or Fragment. This "connection" is important, so you can have your onItemClick method inside your Activity or Fragment and access the members there.

A minimal implementation would look like this (in a Fragment, but you can also use an Activity):

public class YourFragment extends Fragment implements RecyclerViewAdapter.ItemClickListener {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);

        View view = inflater.inflate(R.layout.fragment_your, container, false);

        RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recyclerview);
        RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(activity);
        recyclerViewAdapter.setClickListener(this);
        recyclerView.setAdapter(recyclerViewAdapter);

        return view;
    }

    @Override
    public void onItemClick(View view, int position) {
        // do something here
    }
}

And the Adapter class

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
    private ItemClickListener itemClickListener;

    void setClickListener(ItemClickListener itemClickListener) {
        this.itemClickListener = itemClickListener;
    }

    interface ItemClickListener {
    void onItemClick(View view, int position);
    }

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        // TextView is an example
        final TextView textView;

        ViewHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.text);
            textView.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            if (itemClickListener != null) {
                itemClickListener.onItemClick(view, getAdapterPosition());
            }
        }
    }
}
kalabalik
  • 3,792
  • 2
  • 21
  • 50
  • I am not asking here the solution , i just want to know does this cause any performance problem. Anyway thanks. – Abu Yousuf Oct 01 '17 at 04:48
0

I'm pretty sure the compiler just creates a no-name concrete version of your anonymous class under the hood. That is nearly identical to implementing the interface and providing this as a concrete listener. Realistically, you shouldn't have a performance problem with either.

Just keep in mind that of the fact that an anonymous class holds a reference to the outer class. That might create memory leaks (example: if the outer class is an activity) or just make it so that garbage collection happens all at once instead of small pieces over time. See Implicit and Synthetic Parameters in the oracle documentation for more details on that.

Jon
  • 1,715
  • 12
  • 14