Георги Ангелов Георги Ангелов - 1 month ago 23
Android Question

CardViewAdapter with multiple nested ViewHolders

I have a question which is more of a practical matter.
I'm creating an app which has multiple Cards - each with different information. I am creating the CardViewAdapter and inside I create my ViewHolders for each card. Everything works very well.

My question is - is there a better way of creating the nested classes? Because I have 5 ViewHolders each with 200+ lines of code which makes my CardViewAdapter very hard to read. Is there more practical way of doing that or it is fine like that?

public class CardViewAdapter extends RecyclerView.Adapter<CardViewAdapter.ViewHolder> {

private Context mContext;

public CardViewAdapter(Context context) {
mContext = context;
}

private String[] mDataSet;
private int[] mDataSetTypes;

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
Context context = viewGroup.getContext();
View v;
ViewHolder holder;


if(viewType == 0){
v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card1, viewGroup, false);
return new Card1ViewHolder(v);
} else if(viewType == 1) {
v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card2, viewGroup, false);
return new Card2ViewHolder(v);
} else if(viewType == 2) {
v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card3, viewGroup, false);
return new Card3ViewHolder(v);
} else if(viewType == 3) {
v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card4, viewGroup, false);
return new Card4DialerViewHolder(v);
} else if(viewType == 4) {
v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card5, viewGroup, false);
return new Card5SettingsViewHolder(v);
} else {
return null;
}
}

@Override
public void onBindViewHolder(CardViewAdapter.ViewHolder holder, int position) {

}

@Override
public int getItemCount() {
return 5;
}

@Override
public int getItemViewType(int position) {
int viewType = 0;

if(position == 0){
viewType = 0;
} else if (position == 1){
viewType = 1;
} else if (position == 2){
viewType = 2;
} else if (position == 3){
viewType = 3;
} else if (position == 4){
viewType = 4;
}
return viewType;
}

public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View v) {
super(v);

}
}

private class Card1ViewHolder extends ViewHolder{
//layout 1
}

private class Card2ViewHolder extends ViewHolder{
//layout 2
}

private class Card3ViewHolder extends ViewHolder {
//layout 3
}

private class Card4ViewHolder extends ViewHolder {
//layout 4
}

private class Card5ViewHolder extends ViewHolder {
//layout 5
}


}

Basically inside the 5 ViewHolders I have completely different layout doing different things.

Answer

Declare a base class:

public abstract class Binder {
    public abstract void bind(View view, Hash<Integer, Object> values);
}

So, you can override it for all card views. The next, declare an item class:

public class CardItem {
    public HashMap<Integer, Object> values;
    public int type;
    public Binder binder;
    public bind(View view) {binder.bind(view, values);}
}

So, in the data binding you can fill it like item.bind(holder.view);. Use item.type to create ViewHolder with a correct layout.