2

1) Problem

I would like to set 2 listeners on 2 buttons inside a CardView. I need to know which item has been selected. I use CardView with RecyclerView and FirebaseRecyclerAdapter (RecyclerView.Adapter)

2) Old Situation

I have created the listener in populateViewHolder() of my FirebaseRecyclerAdapter like this:

@Override
protected void populateViewHolder(final ItemViewHolder viewHolder, final Item model, final int position) {

    viewHolder.firstButton.setOnClickListener(new View.OnClickListener() {
        Item selectedItem = getItem(position);
        //do something for the item selected
    }

}

this works fine!

3) What I would like to do

Set listeners in the ViewHolder class (defined in his own file) and do something on the selected ITEM

I would like to set the listeners in the ViewHolder class because the same ViewHolder is used for different adapters and I think it's a better approach to have the behaviour of the listeners defined in only one place.

I did like this:

public class ItemViewHolder extends RecyclerView.ViewHolder {

    public CardView cardView;
    public TextView itemText;
    public ImageView itemFirstButton;
    public ImageView itemSecondButton;

    public ItemViewHolder(View itemView) {
        super(itemView);
        cardView = (CardView)itemView.findViewById(R.id.item_card_view);
        itemText = (TextView)itemView.findViewById(R.id.item_text);
        itemFirstButton = (ImageView)itemView.findViewById(R.id.ic_first_action);
        itemSecondButton = (ImageView)itemView.findViewById(R.id.ic_second_action);

        itemFirstButton.setOnClickListener(firstListener);
        itemSecondButton.setOnClickListener(secondListener);
    }


    private View.OnClickListener firstLinstener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int position =  getAdapterPosition();
        }
    };

    private View.OnClickListener secondListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int position = getAdapterPosition();
        }
    };
}

Inside the listener I can't get any reference on the item, just the position...

I have the impression I have to declare an interface for the listener and pass to the adapter, but I don't know how.

Does it make still sense to declare the listeners in the viewholder or I keep them in the adapter as the old solution?

K Neeraj Lal
  • 6,768
  • 3
  • 24
  • 33
DavideN
  • 253
  • 2
  • 11
  • Nop. It does not makes sense for me to put the listeners inside the ViewHolder when you need something from adapter. Since the view is constantly destroy and re-created during the scroll, you need to define it during onBind. If your listener does something generic and not dependent on any adapter data then it makes sense to put it inside viewHolder. – Panther Sep 14 '16 at 14:25
  • Hi Panther, my listener does something that is dependent on the item (example clicking a button I want to share the item data). The share action is hovewer the same behaviour for 2 different adapters that use the same ViewHolder. So if I well understood you suggest to keep the listener inside the adapters... – DavideN Sep 15 '16 at 14:14
  • Yes, i suggest you to keep the listener inside the adapters. However, since you are mentioning that the action is same, i believe you are trying to arrive at a DRY solution. What i would do in your case is to write a common function to perform all the shares. The listeners would just be a proxy who will invoke the share action with appropriate data. – Panther Sep 15 '16 at 18:47

2 Answers2

0

If you want to tell your position to the adapter, just pass the some interface through ViewHolder constructor. OR the previous way.

The point is whom you want to delegate the position to.

neonankiti
  • 61
  • 5
0

Yes it is good practice to use interface. Create an interface like

public interface OnClick {
    void getItem(int item);
}

Then setOnClicklistner like

itemViewHolder. itemText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                OnClick onClick = (OnClick)context;
                onClick.getItem(position);
            }
        });

Then in your activity implement that method. From this you get position. Then by using position you get elements from array.

e.k
  • 1,333
  • 1
  • 17
  • 36
  • Hi thanks for the answer... sorry but it's not really clear for me how to do it. Do I have to set the listener on the adapter? Let's say I would like to have a listener defined in the ViewHolder that is able to implement a share action to share the item data selected (so the onClick behaviour should be defined in the ViewHolder). How can i pass the item from the Adapter to the ViewHolder? – DavideN Sep 15 '16 at 14:20