Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle a lot of different view types in recyclerview viewholder

What if I have 50 types of views? Should I have 50 static inner classes in my adapter? According to this answer, yes.

My first thought was to move each viewholder inner class into a seperate public class, but they have to be static. So encapsulate each one into a public class, to make the inner class static? Are there any nicer alternatives?

edit: code sample: So this would be a good solution? Doesn't this also kill performance?

public class MainViewHolder extends DragSortAdapter.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
View container;
TextView title;

//called in onCreateViewHolder in adapter
public MainViewHolder(DragSortAdapter adapter, View itemView) {
    super(adapter, itemView);

    container = itemView.findViewById(R.id.card_root);

    title = container.findViewById(R.id.text);
}
//called by onBindViewHolder in adapter
public void setData(Data data) {
    title.setText(data.title);
}
}

edit2: sample, for when a new instance is returned of the viewholder

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
     switch (viewType) {
         case 0: return new MainViewHolder(...);
         case 2: return new MainViewHolderOther(...);
         ...
     }
}
like image 384
Tamas Avatar asked Mar 12 '15 09:03

Tamas


1 Answers

You can use only one viewHolder inner class to handle lots of different viewType. Firstly you have to use getItemViewType(viewType) to get the item position and also have to use viewHolder according to viewType Position.

Make One vieHolder inner class in which you can pass view and viewtype according to position of item and inflate the layout as shown below code. Code sample is given below.

public class Adapter extends
        RecyclerView.Adapter<Adapter.MyViewholder> {

LayoutInflater inflater;
private Context context;
ArrayList<Detail> data = new ArrayList<Detail>();

public Adapter(Context context, ArrayList<Detail> getdata) {
    this.context = context;
    inflater = LayoutInflater.from(context);
    this.data = getdata;
}

class MyViewholder extends RecyclerView.ViewHolder {
    TextView txtRow, txt_rec;

    public MyViewholder(View view, int type) {
        super(view);

        if (type == Constants.NORMAL) {
            txtRow = (TextView) view
                    .findViewById(R.id.txtRow);
        } else if (type == Constants.RECORDING) {
            txt_rec = (TextView) view
                    .findViewById(R.id.txt_rec);
        } 
    }
}

@Override
public int getItemCount() {
    return data.size();
}

@Override
public void onBindViewHolder(MyViewholder viewholder, int position) {
    int listViewItemType = getItemViewType(position);
    Detail detail = data.get(listViewItemType);
    if (detail.getType() == Constants.NORMAL) {
        viewholder.txtRow.setText(detail.getKey());
    } else if (detail.getType() == Constants.RECORDING) {
        viewholder.txt_rec.setText(detail.getRecording());
    } 

}

@Override
public MyViewholder onCreateViewHolder(ViewGroup parent, int viewType) {

    int listViewItemType = getItemViewType(viewType);
  switch (listViewItemType) {
         case 0: 
              view = inflater.inflate(R.layout.detail_item, parent,
                    false);
            myViewholder = new MyViewholder(view, Constants.NORMAL);
         case 2: 
             view = inflater.inflate(R.layout.recording, parent, false);
            myViewholder = new MyViewholder(view, Constants.RECORDING);
    }
    return myViewholder;
}

@Override
public int getItemViewType(int position) {
        return position;
    }
}

Hope this code will help you

like image 72
Amandeep Rohila Avatar answered Nov 03 '22 00:11

Amandeep Rohila