I have a RecyclerView adapter that takes care of several view types which I've been using for years. Recently, I found out about ConcatAdapter, but I seem to be running into an issue where it seems to be returning the wrong value for getItemViewType().
I have a use case where I want to show a header and below it a list of items. I've created a new adapter class for the header, but the list items will continue using my old adapter (that also takes care of several other view types).
So I've concatenated the two adapters:
HeaderAdapter headerAdapter = new HeaderAdapter(context);
PostAdapter postAdapter = new PostAdapter(context, postData);
ConcatAdapter concatAdapter = new ConcatAdapter(headerAdapter, postAdapter);
recyclerView.setAdapter(concatAdapter);
This works fine, but when I go to open the activity, it immediately crashes and gives the error:
java.lang.ClassCastException: com.myapp.android.adapter.PostAdapter$PostViewHolder cannot be cast to com.myapp.android.adapter.PostAdapter$FooterViewHolder
Which makes no sense because I never even added a footer to the recycler view.
My getItemViewType() method in PostAdapter looks something like this:
@Override
public int getItemViewType(int position) {
if (data.get(position) instanceof Footer) {
return TYPE_FOOTER;
} else if (data.get(position) instanceof Post) {
return TYPE_POST;
}
return -1;
}
And my onBindViewHolder() looks something like this:
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case TYPE_FOOTER:
FooterViewHolder vh1 = (FooterViewHolder) holder;
configureFooterViewHolder(vh1, position);
break;
case TYPE_POST:
PostViewHolder vh2 = (PostViewHolder) holder;
configurePostViewHolder(vh2, position);
break;
default:
break;
}
}
But for whatever reason, when I run the debugger, it lands on the line FooterViewHolder vh1 = (FooterViewHolder) holder;, even though I never included a footer as part of the PostAdapters data.
So why is it landing on this? Why would ConcatAdapter cause such strange behaviour in an adapter that handles multiple view types?

When you bind the view holders, you should use RecyclerView.Adapters.getItemViewType(position), not RecyclerView.ViewHolder.getItemViewType():
You got an error because the view holder was recycled, it could be any view holder, therefore it threw
ClassCastExceptionwhen you forced to cast it to a wrong class.