Search code examples
javaandroidandroid-recyclerviewandroid-adapterandroid-viewholder

Best way to notify RecyclerView Adapter from Viewholder?


I have a RecyclerView with multiple item view types so they are broken into separate ViewHolder classes. Before, when all the ViewHolders were in the same class as the RecyclerView Adapter, I could update the adapter directly when an item was clicked or deleted. However, I separated the ViewHolders into different classes to better organize the code. Now, I cannot directly update my RecyclerView Adapter. Which of the following solutions is the best way to communicate from my ViewHolder to my Adapter? If there is a better solution than the ones I have listed, please suggest!

  1. Using a Interface with a Callback listener. Keep in mind that there might be 5 - 10 different view types so would this method require 5 - 10 interfaces?
    1. Use an Eventbus library such as Greenrobot's Eventbus.

Is an interface or eventbus solution really the best way? There surely has to be a better method for communication between views and adapters!


Solution

  • I usually save reference to the adapter in activity or fragment. ViewHolders can be placed as inner classes in Adapter or as classes in separate package. You can use one interface to interact with view holders. You just need to implement it in your activity or fragment. For Example:

    public class MyAdapter extends RecyclerView.Adapter<VH> {
        private MyInterface mInterface;
    
        public MyAdapter(MyInterface i) {
             mInterface = i;
        }
    
        //... some code to create view holders
    
    
        //binding
        @Override
        protected void onBindItemViewHolder(ViewHolder viewHolder, final int position, int type) {
            viewHolder.bindView(position, mInterface); //call methods of interface in bindView() methods of your viewHolders
        }
    
        interface MyInterface {
            void someEvent();
        }
    }
    
    public class ViewHolder extends RecyclerView.ViewHolder {
    
        TextView mText;
    
        ViewHolder(View root) {
            super(root);
            mText = (TextView)root.findViewById(R.id.text)
        }
    
        void bindView(int pos, MyAdapter.MyInterface myInterface) {
            mText.setOnClickListener(v -> myInterface.someEvent());
            //...some other code
        }
    }
    

    And somewhere in your activity or fragment:

    final MyAdapter adapter = new MyAdapter(new MyAdapter.MyInterface() {
        @Override
        public void someEvent() {
            adapter.notifyDataSetChanged();
        }
    });