多个 ViewHolder RecycleVIew 列表重新排列

Multiple ViewHolder RecycleVIew List rearrange

我试图找到解决方案,但我认为没有人遇到过这样的问题。

所以我在我的大部分项目中都使用了 ListView,我觉得它更灵活,因为你不需要 BindViewHolder RecyclerView。但是因为我需要制作水平 listview,所以我可以使用 RecyclerView 使用 LayoutManager 轻松做到这一点。它工作得很好。

但现在我为 RecyclerView 使用了多个 ViewHolders,因为我需要为 RecyclerView 的不同项目显示不同的视图。它再次使用下面的代码完美运行。

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();
    }

}

因此,当我重新排列用于显示项目的列表时,问题就出现了。例如,我从 TYPEB 列表中的 1 项开始,它显示正确。但现在我想在列表中添加新项目,但在开始时,以便 TYPEB 被推回。所以我添加了一个 TYPEA 的新项目,列表看起来像 [TYPEA,TYPEB]ViewHolderA 用于 TYPEA 类似地 ViewHolderB 用于 TYPEB

在这种情况下 onBindViewHolder

内的行
ViewHolderA viewHolder = (ViewHolderA) holder;

向我抛出一个错误,指出 ViewHolderB 无法转换为 ViewHolderA。这表明在重新排列列表后,适配器正在调用 onBindViewHolder,并针对 positon 使用错误的 ViewHolder 实例。知道如何处理这个问题。

你需要在这里指定一个唯一的id,你不必return位置:

@Override
public int getItemViewType(int position) {        
    return data.get(position).getType()
}

当然,您必须将 viewType 参数用作类型而不是位置:

@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);
    }
}