5

I am following a RecyclerView example and I have this error

incompatible types: cannot cast viewholder to imageviewholder

on this code

case TYPE_IMAGE:
            ImageViewHolder imageViewHolder = (ImageViewHolder) holder;

this is my full code(edited)

public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private ArrayList<String> mDataset;

    public class ImageViewHolder extends RecyclerView.ViewHolder {
        //ImageView mImage;
        public TextView txtHeader;
        public TextView txtFooter;
        public ImageViewHolder(View itemView) {
            super (itemView);
            txtHeader = (TextView) itemView.findViewById(R.id.firstLine1);
            txtFooter = (TextView) itemView.findViewById(R.id.secondLine1);
        }
    }

    // Provide a reference to the views for each data item
    // Complex data items may need more than one view per item, and
    // you provide access to all the views for a data item in a view holder
    public class TextViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case
        public TextView txtHeader;
        public TextView txtFooter;

        public TextViewHolder(View v) {
            super(v);
            txtHeader = (TextView) v.findViewById(R.id.firstLine);
            txtFooter = (TextView) v.findViewById(R.id.secondLine);
        }
    }

    public void add(int position, String item) {
        mDataset.add(position, item);
        notifyItemInserted(position);
    }

    public void remove(String item) {
        int position = mDataset.indexOf(item);
        mDataset.remove(position);
        notifyItemRemoved(position);
    }

    // Provide a suitable constructor (depends on the kind of dataset)
    public MyAdapter(ArrayList<String> myDataset) {
        mDataset = myDataset;
    }

    // Create new views (invoked by the layout manager)
    @Override
    public RecyclerView.ViewHolder  onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {
        // create a new view
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.rowlayout, parent, false);
        // set the view's size, margins, paddings and layout parameters
        TextViewHolder vh = new TextViewHolder(v);
        return vh;
    }

    private static final int TYPE_IMAGE = 1;
    private static final int TYPE_GROUP = 2;

    @Override
    public int getItemViewType(int position) {
        // here your custom logic to choose the view type
        return position == 0 ? TYPE_IMAGE : TYPE_GROUP;
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder TextViewHolder, int position) {

        switch (TextViewHolder.getItemViewType()) {

            case TYPE_IMAGE:
                ImageViewHolder imageViewHolder = (ImageViewHolder) TextViewHolder;
               // imageViewHolder.mImage.setImageResource(...);
                final String namev = mDataset.get(position);
                imageViewHolder.txtHeader.setText(mDataset.get(position));
                imageViewHolder.txtHeader.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        remove(namev);
                    }
                });

                break;

            case TYPE_GROUP:
                TextViewHolder viewHolder = (TextViewHolder) TextViewHolder;
              //  viewHolder.txtHeader.setText(...)
                final String name = mDataset.get(position);
                viewHolder.txtHeader.setText(mDataset.get(position));
                viewHolder.txtHeader.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        remove(name);
                    }
                });

                viewHolder.txtFooter.setText("Footer: " + mDataset.get(position));

                break;
        }
/*
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        final String name = mDataset.get(position);
        holder.txtHeader.setText(mDataset.get(position));
        holder.txtHeader.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                remove(name);
            }
        });

        holder.txtFooter.setText("Footer: " + mDataset.get(position));
*/
    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return mDataset.size();
    }

}

error here

@Override
public RecyclerView.ViewHolder  onCreateViewHolder(ViewGroup parent,
                                               int viewType) {
    switch (viewType) {

        case TYPE_IMAGE: {
            View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.rowlayout, parent, false);
            // return new ImageViewHolder(itemView);
            ImageViewHolder vh = new ImageViewHolder(itemView);
            return vh;
        }
        case TYPE_GROUP: {
            View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.rowlayout, parent, false);
            // return new TextViewHolder(itemView);
            TextViewHolder vh = new TextViewHolder(itemView);
            return vh;
        }
    }
}// error here missing return statement
Moudiz
  • 7,211
  • 22
  • 78
  • 156
  • Does ImageViewHolder extend or implement ViewHolder? If not, that cast won't work. – Gabe Sechan Jan 29 '16 at 23:28
  • @GabeSechan yes as I have posted in my code `public class ImageViewHolder extends RecyclerView.ViewHolder {` – Moudiz Jan 29 '16 at 23:33
  • You have `MyAdapter` extending `RecyclerView.Adapter` and `ImageViewHolder` extending `RecyclerView.ViewHolder`. – andrea.petreri Jan 29 '16 at 23:34
  • 2
    No it doesn't. ImageViewHolder extends RecyclerView.ViewHolder. And ViewHolder extends RecyclerView.ViewHolder. But ImageViewHolder does not extend ViewHolder. By reusing the name you confused yourself and the compiler (and me as I typoed the initial draft of this) – Gabe Sechan Jan 29 '16 at 23:34
  • Rather only himself... Compiler did get confused and gave an error... – Selvin Jan 29 '16 at 23:37
  • @GabeSechan most of my code was from this SO [answer](http://stackoverflow.com/questions/25914003/recyclerview-and-handling-different-type-of-row-inflation/29362643#29362643) so I need to remove the exend from imageview holder ? how to make things clear to me and to the compiler – Moudiz Jan 29 '16 at 23:38
  • The best way- change the name of the ViewHolder class you define here to TextViewHolder. Then its clear which of the two classes you mean at all times. Then fix any compilation issues caused by that change. – Gabe Sechan Jan 29 '16 at 23:40
  • You should make `MyAdapter` extending `RecyclerView.Adapter` and change types in overridden methods `onBindViewHolder` and `onCreateViewHolder` accordingly. In this way you shouldn't have any other issue with cast. – andrea.petreri Jan 29 '16 at 23:45
  • @GabeSechan sorry I am bit lost, is it correct what I did ? check please my edit – Moudiz Jan 29 '16 at 23:50
  • onBindViewHolder needs to take a RecyclerView.ViewHolder as its first parameter. – Gabe Sechan Jan 29 '16 at 23:52

2 Answers2

4

You should change:

 public class MyAdapter extends RecyclerView.Adapter<MyAdapter.TextViewHolder> 

for:

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

And then change your onCreateViewHolder in order to accept multiple ViewTypes:

    @Override
    public MyAdapter.TextViewHolder onCreateViewHolder(ViewGroup parent,
                                               int viewType)

for:

   @Override
   public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,
                                               int viewType)

And then change the onBindViewHolder method:

 @Override
 public void onBindViewHolder(TextViewHolder TextViewHolder, int position) 

for:

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

And don´t forget to set your ViewHolder types:

   @Override
   public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,
                                               int viewType){
    switch (viewType) {

       case TYPE_IMAGE: {
            View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.XXX, parent, false);
            return new ImageViewHolder(itemView);
            }
       case TYPE_GROUP: {
            View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.XXX, parent, false);
            return new TextViewHolder(itemView);
           }
      }
JpCrow
  • 4,881
  • 4
  • 32
  • 46
  • what about this line , I have changed like this ,is it correct ? public void onBindViewHolder(RecyclerView.ViewHolder TextViewHolder, int position) { – Moudiz Jan 29 '16 at 23:59
  • I had this error java.lang.ClassCastException: com..www.i.MyAdapter$TextViewHolder cannot be cast to com..www.i.MyAdapter$ImageViewHolder check my edit answer for my latest code – Moudiz Jan 30 '16 at 00:07
  • Check my last edit, you are not setting the viewholders! – JpCrow Jan 30 '16 at 00:08
4

This is updated file:

public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private ArrayList<String> mDataset;

    public class ImageViewHolder extends RecyclerView.ViewHolder {
        //ImageView mImage;
        public TextView txtHeader;
        public TextView txtFooter;
        public ImageViewHolder(View itemView) {
            super (itemView);
            txtHeader = (TextView) itemView.findViewById(R.id.firstLine1);
            txtFooter = (TextView) itemView.findViewById(R.id.secondLine1);
        }
    }

    // Provide a reference to the views for each data item
    // Complex data items may need more than one view per item, and
    // you provide access to all the views for a data item in a view holder
    public class TextViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case
        public TextView txtHeader;
        public TextView txtFooter;

        public TextViewHolder(View v) {
            super(v);
            txtHeader = (TextView) v.findViewById(R.id.firstLine);
            txtFooter = (TextView) v.findViewById(R.id.secondLine);
        }
    }

    public void add(int position, String item) {
        mDataset.add(position, item);
        notifyItemInserted(position);
    }

    public void remove(String item) {
        int position = mDataset.indexOf(item);
        mDataset.remove(position);
        notifyItemRemoved(position);
    }

    // Provide a suitable constructor (depends on the kind of dataset)
    public MyAdapter(ArrayList<String> myDataset) {
        mDataset = myDataset;
    }

    // Create new views (invoked by the layout manager)
    @Override
    public RecyclerView.ViewHolder  onCreateViewHolder(ViewGroup parent,
                                                       int viewType) {
        if (viewType == TYPE_IMAGE) {
            // create a new view
            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.rowlayout, parent, false);
            // set the view's size, margins, paddings and layout parameters
            ImageViewHolder vh = new ImageViewHolder(v);
            return vh;
        } else {
            // create a new view
            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.rowlayout, parent, false);
            // set the view's size, margins, paddings and layout parameters
            TextViewHolder vh = new TextViewHolder(v);
            return vh;
        }
    }

    private static final int TYPE_IMAGE = 1;
    private static final int TYPE_GROUP = 2;

    @Override
    public int getItemViewType(int position) {
        // here your custom logic to choose the view type
        return position == 0 ? TYPE_IMAGE : TYPE_GROUP;
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder TextViewHolder, int position) {

        switch (TextViewHolder.getItemViewType()) {

            case TYPE_IMAGE:
                ImageViewHolder imageViewHolder = (ImageViewHolder) TextViewHolder;
                // imageViewHolder.mImage.setImageResource(...);
                final String namev = mDataset.get(position);
                imageViewHolder.txtHeader.setText(mDataset.get(position));
                imageViewHolder.txtHeader.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        remove(namev);
                    }
                });

                break;

            case TYPE_GROUP:
                TextViewHolder viewHolder = (TextViewHolder) TextViewHolder;
                //  viewHolder.txtHeader.setText(...)
                final String name = mDataset.get(position);
                viewHolder.txtHeader.setText(mDataset.get(position));
                viewHolder.txtHeader.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        remove(name);
                    }
                });

                viewHolder.txtFooter.setText("Footer: " + mDataset.get(position));

                break;
        }
/*
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        final String name = mDataset.get(position);
        holder.txtHeader.setText(mDataset.get(position));
        holder.txtHeader.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                remove(name);
            }
        });

        holder.txtFooter.setText("Footer: " + mDataset.get(position));
*/
    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return mDataset.size();
    }

}
andrea.petreri
  • 4,137
  • 2
  • 22
  • 21
  • I did what you write , but I have this error , check please my update code java.lang.ClassCastException: com..www.i.MyAdapter$TextViewHolder cannot be cast to com..www.i.MyAdapter$ImageViewHolder – Moudiz Jan 30 '16 at 00:03
  • @Moudiz you are now having this error at runtime? I'm asking because implementation of onCreateViewHolder doesn't take care of view type – andrea.petreri Jan 30 '16 at 00:08
  • updated... even if I don't know which are layouts for views – andrea.petreri Jan 30 '16 at 00:11
  • I am having error mssing return statement return vh; } //here is the error in the last brackets of the class } – Moudiz Jan 30 '16 at 00:17
  • @Moudiz you copied the whole file I posted? I don't see errors related to missing return... I mean... putting code in Android Studio. – andrea.petreri Jan 30 '16 at 00:21
  • @Moudiz code shouldn't have issues at compile time... a problem that may occur is that R.layout.rowlayout is used both for ImageViewHolder and TextViewHolder. I don't know if it it correct. – andrea.petreri Jan 30 '16 at 00:23
  • 1
    @Moudiz glad I could help! :) – andrea.petreri Jan 30 '16 at 00:26