atabouraya
atabouraya

Reputation: 3332

Is it a bad practice to hold a reference for the list item inside the ViewHolder

I usually use an interface to handle clicks on the list item, either to show a message, or take an action

public interface ItemClickListener {
void onItemClicked(int adapterPosition);
}

@OnClick(R.id.seat_btn)
protected void click() {
    if (mItemClickListener != null)
        mItemClickListener.onItemClicked(getAdapterPosition());
}

However sometimes it's a lot easier sometimes to hold a reference for the object inside the ViewHolder and update it with each onBindViewHolder call and handling all the actions and changes inside the ViewHolder

Seat mSeat;
@OnClick(R.id.seat_btn)
protected void click() {
   seatView.setText(String.value(mSeat.getCount()+1));
}

So my question is "is that considered a bad practice?"

Upvotes: 2

Views: 270

Answers (1)

Budius
Budius

Reputation: 39836

Yes and No.

  • Yes:

There's nothing wrong to have your data object inside the view holder. I've even seen adapters before with lots of ViewTypes that used a base ViewHolder with a generic parameter T and an abstract method to bind the view to the data, like this:

abstract BaseHolder<T> extends ViewHolder {
   .... constructor...
   private T t;

   abstract void bindView(T t);
}

It's a nice pattern, isolates the view binding to the ViewHolder and the Adapter simply distributes this data to the right holders.

  • But no:

On the other hand, directly handle click/tap events inside those same holders I consider bad practice as it should not be the ViewHolder responsibility to do it.

App navigation, generate network calls or database insert is something that should be passed back to the top view layer (activity or fragment) or to some Controller that can properly handle the logic isolated from the view rendering.

Normally on those cases the the you would create a OnEventHappened interface, for example like this:

public interface onEventHappen {
    void onLikeTapped(MyData data);
}

and the class that implements that interface should be passed to the adapter that will pass to the ViewHolder. The ViewHolder implements the basic View.OnClickListener and passes the event with the associated data to the object responsible to handle that event. Something like this:

MyHolder extends ViewHolder implements View.OnClickListener {

     private final EventListener listener;
     private MyData data; // this will be set by adapter or "bind" like explained above

     public MyHolder(View itemView, EventListener listener) {
         super(itemView);
         itemView.findVieById(R.id.button).setOnClickListener(this);
         this.listener = listener;
     }

     @Override public void onClick(View view) {
        listener.onEvent(data);
     }
}

I hope it helps.

Upvotes: 3

Related Questions