How to call a MainActivity method from ViewHolder in RecyclerView.Adapter?

前端 未结 5 1156
眼角桃花
眼角桃花 2020-12-09 05:45

In a simple app project at GitHub I have only 2 custom Java-files:

  1. MainActivity.java contains Bluetooth- and UI-related source code
  2. DeviceListAdapter.
相关标签:
5条回答
  • 2020-12-09 06:01

    To keep your classes decoupled, I'd suggest defining an interface on your adapter, something like:

    public interface OnBluetoothDeviceClickedListener {
        void onBluetoothDeviceClicked(String deviceAddress);
    }
    

    Then add a setter for this in your adapter:

    private OnBluetoothDeviceClickedListener mBluetoothClickListener;
    
    public void setOnBluetoothDeviceClickedListener(OnBluetoothDeviceClickedListener l) {
        mBluetoothClickListener = l;
    }
    

    Then internally, in your ViewHolder's onClick():

    if (mBluetoothClickListener != null) {
        final String addresss = deviceAddress.getText().toString();
        mBluetoothClickListener.onBluetoothDeviceClicked(address);
    }
    

    Then just have your MainActivity pass in a listener to the Adapter:

    mDeviceListAdapter.setOnBluetoothDeviceClickedListener(new OnBluetoothDeviceClickedListener() {
        @Override
        public void onBluetoothDeviceClicked(String deviceAddress) {
            confirmConnection(deviceAddress);
        }
    });
    

    This way you can reuse the adapter later without it being tied to that particular behavior.

    0 讨论(0)
  • 2020-12-09 06:05

    For those who are looking for invoking a callback from a static ViewHolder do the following. Let you have an adapter:

    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
        private final int resource;
        private final List<Item> items;
        private final LayoutInflater inflater;
        ...
        private Callback callback;
    
        private static class ViewHolder extends RecyclerView.ViewHolder {
            ...
        }
    
        public interface Callback {
            void onImageClick(int position);
            void onRemoveItem(int position);
        }
    }
    

    Then you should add a setCallback method and call it from activity/fragment. Also you shouldn't make a callback static (it may lead to problems when you use the same adapter in many classes). You should create a field inside the ViewHolder. So:

        public MyAdapter(Context context, int resource, List<Item> items, Callback callback) {
            super();
            this.resource = resource;
            this.items = items;
            this.inflater = LayoutInflater.from(context);
            this.callback = callback;
        }
    
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            final ViewHolder viewHolder = (ViewHolder) holder;
            final Item item = this.items.get(position);
            viewHolder.caption.setText(item.caption);
            viewHolder.callback = callback;
        }
    
        // A method to set a callback from activity/fragment.
        public void setCallback(Callback callback) {
            this.callback = callback;
        }
    
        public static class Item {
            public long id;
            public String number;
            public String caption;
    
            ...
        }
    
        private static class ViewHolder extends RecyclerView.ViewHolder {
            protected final TextView caption;
            // A reference to an adapter's callback.
            protected Callback callback;
    
            public ViewHolder(View view) {
                super(view);
                this.caption = (TextView) view.findViewById(R.id.caption);
            }
    
            private View.OnClickListener onClickListener = new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int id = v.getId();
                    if (id == R.id.image) {
                        // Invoke the callback here.
                        if (callback != null) {
                            callback.onImageClick(getLayoutPosition());
                        }
                    }
                }
            };
        }
    }
    

    After you have made the adapter you can invoke it so:

    adapter = new MyAdapter(getActivity(), R.layout.item,
            new ArrayList<MyAdapter.Item>(), null);
    
    adapterListener = new MyAdapter.Callback() {
        @Override
        public void onImageClick(int position) {
            // Some actions.
        }
    
        @Override
        public void onRemoveItem(int position) {
            // Some actions.
        }
    };
    
    adapter.setCallback(adapterListener);
    
    0 讨论(0)
  • 2020-12-09 06:05

    You can call Activity method by using instance of Activity like this, inside MainActivity write below code

    mDeviceListAdapter = new DeviceListAdapter(MainActivity.this);
    

    Inside Adapter

     private MainActivity _mainActivity;
     public DeviceListAdapter(MainActivity activity){
     this._mainActivity=activity;
     }
    

    Inside your onClick method

     _mainActivity.yourActivityMethod(address);
    
    0 讨论(0)
  • 2020-12-09 06:11

    In your adapter, create an interface that will provide a callback to the main activity

    public interface MyCallback{
        void onItemClicked();
    }
    
    private MyCallback listener;
    
    public setOnItemClickListener(MyCallback callback){
        listener = callback;
    }
    

    Have your main activity implement it.

    public class MainActivity extends AppCompatActivity implements MyCallback
    

    then implement the callback

    @Override
    public void onItemClick(){
        //do work
    }
    

    then just set the callback from the adapter

    mDeviceListAdapter.setOnItemClickListener(this);
    
    0 讨论(0)
  • 2020-12-09 06:14

    You could pass the MainActivity as a constructor-parameter for the Adapter and store it in a field. Or you use a event-bus - there are multiple ways to do it - I would go for the field

    0 讨论(0)
提交回复
热议问题