Search code examples
androidandroid-adapterandroid-recyclerviewandroid-viewholder

ClassCastException custom ViewHolder cannot be cast to another Viewholder


my project should create multiple views based on user input (user send text, take a photo or record a video) similar to WhatsApp chat activity, almost same structure. The adapter should be able to identify which type of view the item is, by using getItemViewType(). if try to use video record functionality it works but if I try to take a photo or send a text the app crashes with the following error:

java.lang.ClassCastException: AppPackage.myAdapter$TextViewHolder cannot be cast to AppPackage.myAdapter$ImageViewHolder

all data taken from inputs is added to a List which then is passed to the onBindViewHolder

already tried to change onBindViewHolder( CustomViewHolder myViewHolder, int position) to onBindViewHolder(RecyclerView.ViewHolder, int position) and to add breaks at the of every "case" of the switch. still not working


Adapter

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

List<ModelloDati> lista;
Context context;


public class ImageViewHolder extends RecyclerView.ViewHolder {
    //ImageView mImage;
    private ImageView imageView;
    public ImageViewHolder(View itemView) {
        super (itemView);
        imageView = itemView.findViewById(R.id.immagine);
    }
}

public class TextViewHolder extends RecyclerView.ViewHolder {
    // each data item is just a string in this case
    private TextView titolo;

    public TextViewHolder(View v) {
        super(v);
        titolo = itemView.findViewById(R.id.testo);
    }
}

public class VideoViewHolder extends RecyclerView.ViewHolder {
    // each data item is just a string in this case
    private VideoView videoView;

    public VideoViewHolder(View v) {
        super(v);
        videoView = itemView.findViewById(R.id.rec);
    }
}

public myAdapter(List<ModelloDati> lista,Context context) {
    this.lista = lista;
    this.context = context;

}


@Override
public RecyclerView.ViewHolder  onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {
    if (viewType == 0) {
        // create a new view
        View v =  
LayoutInflater.from(parent.getContext()).inflate(R.layout.item_chat_foto, 
parent, false);
        // set the view's size, margins, paddings and layout parameters
        ImageViewHolder vh = new ImageViewHolder(v);
        return vh;
    }
    if (viewType == 2) {
        // create a new view
        View v = 
LayoutInflater.from(parent.getContext()).inflate(R.layout.item_chat_video, 
parent, false);
        // set the view's size, margins, paddings and layout parameters
        VideoViewHolder vh = new VideoViewHolder(v);
        return vh;
    } else {
        // create a new view
        View v = 
LayoutInflater.from(parent.getContext()).inflate(R.layout.item_chat_testo,  
parent, false);
        // set the view's size, margins, paddings and layout parameters
        TextViewHolder vh = new TextViewHolder(v);
        return vh;
    }
}


@Override
public int getItemViewType(int position){

        switch (lista.get(position).getTYPE()) {
            case 0: return 0;
            case 1: return 1;
            case 2: return 2;
        }
        return 0;

    }


@Override
public int getItemCount() {
        if (lista == null)
            return 0;
        return lista.size();
    }


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

        ModelloDati oggetto = lista.get(position);

        switch (myViewHolder.getItemViewType()) {

            case 0:
                TextViewHolder viewHolder = (TextViewHolder) myViewHolder;
                viewHolder.titolo.setText(oggetto.getTesto());
                break;

            case 1:
                ImageViewHolder imageViewHolder = (ImageViewHolder) 
myViewHolder;

imageViewHolder.imageView.setImageBitmap(oggetto.getImmagini());
                imageViewHolder.imageView.setOnClickListener(new 
View.OnClickListener() {
                    @Override
                    public void onClick(View v) {

                    }
                });

                break;


            case 2:
                VideoViewHolder videoViewHolder = (VideoViewHolder) 
myViewHolder;
                videoViewHolder.videoView.setVideoURI(oggetto.getUri());
                MediaController mediaController = new 
MediaController(context);
                mediaController.setAnchorView(videoViewHolder.videoView);

videoViewHolder.videoView.setMediaController(mediaController);
                videoViewHolder.videoView.requestFocus();
                videoViewHolder.videoView.start();

                videoViewHolder.videoView.setOnClickListener(new 
View.OnClickListener() {
                    @Override
                    public void onClick(View v) {

                    }
                });
                break;

                default:
                    viewHolder = (TextViewHolder) myViewHolder;
                    viewHolder.titolo.setText("ERRORE");


        }

    }


}

LogCat

2019-05-21 10:24:18.728 11089-11089/com.sinfo.chat E/AndroidRuntime: FATAL  
EXCEPTION: main
Process: com.sinfo.chat, PID: 11089
java.lang.ClassCastException: com.sinfo.chat.myAdapter$TextViewHolder cannot be  
cast to com.sinfo.chat.myAdapter$ImageViewHolder
    at com.sinfo.chat.myAdapter.onBindViewHolder(myAdapter.java:119)
    at 

android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6781)
    at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6823)
    at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5752)
    at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6019)
    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5858)
    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5854)
    at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2230)
    at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1557)
    at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
    at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:587)
    at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924)
    at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:3336)
    at android.view.View.measure(View.java:23169)
    at android.support.constraint.ConstraintLayout.internalMeasureChildren(ConstraintLayout.java:1227)
    at android.support.constraint.ConstraintLayout.onMeasure(ConstraintLayout.java:1572)
    at android.view.View.measure(View.java:23169)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
    at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143)
    at android.view.View.measure(View.java:23169)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749)
    at android.support.v7.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:401)
    at android.view.View.measure(View.java:23169)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
    at android.view.View.measure(View.java:23169)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:825)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:704)
    at android.view.View.measure(View.java:23169)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
    at com.android.internal.policy.DecorView.onMeasure(DecorView.java:716)
    at android.view.View.measure(View.java:23169)
    at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2725)
    at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1575)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1858)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1463)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7190)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)
    at android.view.Choreographer.doCallbacks(Choreographer.java:761)
    at android.view.Choreographer.doFrame(Choreographer.java:696)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6718)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Solution

  • ImageViewHolder gets created with type 0 in onCreateViewHolder and casted with type 1 in onBindViewHolder. Use constants instead of floating magic numbers