Reputation: 3155
I tried to find the solution but I think nobody had such a problem.
So I have been using ListView
in most of my projects and I feel it is more flexible in terms of not having to Bind
with ViewHolder
as you need to do in RecyclerView
. But since I needed to make a horizontal listview
I could easily do that with LayoutManager
using RecyclerView
. It works perfectly.
But now I am using multiple ViewHolders
for RecyclerView
because I need to display different views for different items of the RecyclerView
. It again works perfectly using the code below.
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Item> data;
private Context context;
// Item.Type is an enum, used to differentiate the view types.
public MyAdapter(List<Item> list, Context context) {
this.data = list;
this.context = context;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(data.get(viewType).getType() == TYPEA) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.type_a, parent, false);
return new ViewHolderA(itemView);
}
else {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.type_b, parent, false);
return new ViewHolderB(itemView);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if ( data.get(position).getType()== TYPEA ){
ViewHolderA viewHolder = (ViewHolderA) holder;
...
}
else if (data.get(position).getType()== TYPEB){
ViewHolderB viewHolder = ((ViewHolderB) holder);
...
}
}
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public int getItemCount() {
return data.size();
}
}
So the problem arises when I rearrange the list used to display the items. For instance, I start off with 1 item in the list of TYPEB
, it is displayed correctly. But now I want to add new item in the list but at the start, so that TYPEB
is pushed back. So i add a new item of TYPEA
and the list looks like [TYPEA,TYPEB]
. ViewHolderA
is for TYPEA
and similarly ViewHolderB
for TYPEB
In this situation the line inside onBindViewHolder
ViewHolderA viewHolder = (ViewHolderA) holder;
Throws me an error saying that ViewHolderB
can not be cast to ViewHolderA
. That shows after rearranging the list, the adapter is calling onBindViewHolder
with wrong ViewHolder
instance against the positon
. Any idea how to approach this.
Upvotes: 2
Views: 342
Reputation: 1184
You need to specify a unique id here, you don't have to return the position:
@Override
public int getItemViewType(int position) {
return data.get(position).getType()
}
And of course you have to use the viewType parameter as a type not as a position:
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == TYPEA) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.type_a, parent, false);
return new ViewHolderA(itemView);
}
else {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.type_b, parent, false);
return new ViewHolderB(itemView);
}
}
Upvotes: 2