Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView onCreateViewHolder Return Type Incompatibility With Multiple Custom ViewHolders

Tags:

I'm trying to use multiple ViewHolders in a RecyclerView in order to swap these views out at run time. I have created two classes which extend RecyclerView.ViewHolder:

MenuItemViewHolder

public class MenuItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {      public TextView menuItemText;     public ImageView menuItemPhoto;     public RecyclerViewAdapter rva;      public MenuItemViewHolder(View itemView) {          super(itemView);          itemView.setOnClickListener(this);           rva = caller;          menuItemText = (TextView) itemView.findViewById(R.id.grid_text);          menuItemPhoto = (ImageView) itemView.findViewById(R.id.grid_image);     }      @Override     public void onClick(View view) {           Toast.makeText(view.getContext(), "Clicked Position = " + getPosition(), Toast.LENGTH_SHORT).show();      }  } 

SelectedItemViewHolder

public class SelectedItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {      public TextView menuItemText;     public ImageView menuItemPhoto;     public RecyclerViewAdapter rva;      public SelectedItemViewHolder(View itemView) {         super(itemView);         itemView.setOnClickListener(this);           menuItemText = (TextView) itemView.findViewById(R.id.grid_text_full);          menuItemPhoto = (ImageView) itemView.findViewById(R.id.grid_image_full);     }      @Override     public void onClick(View view) {           Toast.makeText(view.getContext(), "Clicked Position = " + getPosition(), Toast.LENGTH_SHORT).show();     } } 

They are called within my RecyclerViewAdapter class's onCreateViewHolder function:

RecyclerViewAdapter onCreateViewHolder

// Create new views (invoked by the layout manager)      @Override     public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {          switch (viewType) {              case 0:                 View gridItemLayout = LayoutInflater.from(parent.getContext())                         .inflate(R.layout.grid_single, parent, false);                 // set the view's size, margins, paddings and layout parameters                 MenuItemViewHolder vh = new MenuItemViewHolder(gridItemLayout);              case 2:                 View selectedItemLayout = LayoutInflater.from(parent.getContext())                         .inflate(R.layout.grid_single_full, parent, false);                 // set the view's size, margins, paddings and layout parameters                 SelectedItemViewHolder sivh = new SelectedItemViewHolder(selectedItemLayout);                 return sivh;           }     } 

When I try to run the code, I get this error:

Error:(48, 36) error: onCreateViewHolder(ViewGroup,int) in RecyclerViewAdapter cannot override onCreateViewHolder(ViewGroup,int) in Adapter return type ViewHolder is not compatible with MenuItemViewHolder where VH is a type-variable: VH extends ViewHolder declared in class Adapter

So, the issue seems to be that onCreateViewHolder doesn't accept my custom classes as being inherited from RecyclerView.ViewHolder. I'm using Android Studio, so perhaps the issue is there. I'm perplexed since I thought Java inheritance would handle this with no problems. Could someone please propose a solution?

Edit: When I change the return type of onCreateViewHolder to MenuItemViewHolder with only one VH, things work fine. However, this doesn't work when I have multiple VH classes which can be swapped at any time.

like image 610
avgrammer Avatar asked Aug 16 '15 23:08

avgrammer


2 Answers

The RecyclerView.Adapter is a parameterized class that takes in a single ViewHolder type. Your definition probably looks like:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MenuItemViewHolder> 

It should be:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> 

Don't forget to have the right definition for onBindViewHolder as well. You need to override getItemViewType as well.

like image 198
N.T. Avatar answered Sep 27 '22 19:09

N.T.


Full working code

For those who want a full working code. There you go.

 public class YourListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {        private static final int LAYOUT_ONE= 0;       private static final int LAYOUT_TWO= 1;        @Override       public int getItemViewType(int position)       {           if(position==0)              return LAYOUT_ONE;           else              return LAYOUT_TWO;       }        @Override       public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {           View view =null;          RecyclerView.ViewHolder viewHolder = null;           if(viewType==LAYOUT_ONE)          {              view = LayoutInflater.from(parent.getContext()).inflate(R.layout.one,parent,false);             viewHolder = new ViewHolderOne(view);          }          else          {             view = LayoutInflater.from(parent.getContext()).inflate(R.layout.two,parent,false);             viewHolder= new ViewHolderTwo(view);          }          return viewHolder;        }        @Override       public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {            if(holder.getItemViewType()== LAYOUT_ONE)           {               // Typecast Viewholder                // Set Viewholder properties                // Add any click listener if any            }           else {                ViewHolderOne vaultItemHolder = (ViewHolderOne) holder;               vaultItemHolder.name.setText(displayText);               vaultItemHolder.name.setOnClickListener(new View.OnClickListener() {                       @Override                      public void onClick(View v) {                       .......                      }                 });              }          }       //****************  VIEW HOLDER 1 ******************//        public class ViewHolderOne extends RecyclerView.ViewHolder {            public TextView name;            public ViewHolderOne(View itemView) {                super(itemView);                name = (TextView)itemView.findViewById(R.id.displayName);           }       }      //****************  VIEW HOLDER 2 ******************//        public class ViewHolderTwo extends RecyclerView.ViewHolder{            public ViewHolderTwo(View itemView) {           super(itemView);             ..... Do something       }    } } 

Read more

You can read more about creating RecyclerView with multiple ViewHolders

like image 35
Rohit Singh Avatar answered Sep 27 '22 18:09

Rohit Singh