RecyclerView关于notifyItemRemoved的那点小事

526 阅读1分钟

RecyclerView关于notifyItemRemoved的那点小事

RecyclerView很多时候是展示静态的数据,并不会有删除的操作,讲到RecyclerView时,会提到它提供了一个很好的展现删除操作动画的函数,代码片段一般是这样的:

@Override
public void onBindViewHolder(final CommonViewHolder holder, final int position) {
    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mDataList.remove(position);
            notifyItemRemoved(position);
        }
    });
}

这样写的话,很快会产生数据删除错乱和超出索引异常导致崩溃。
原因是函数里面的传入的参数position,它是在进行onBind操作时确定的,在删除单项后,已经出现在画面里的项不会再有调用onBind机会,这样它保留的position一直是未进行删除操作前的postion值。

解决办法也很简单 :

//或者使用holder.getAbsoluteAdapterPosition()
mDataList.remove(holder.getBindingAdapterPosition());
notifyItemRemoved(holder.getBindingAdapterPosition());

请注意,如果您要查询RecyclerView所看到的位置,则应使用getAbsoluteAdapterPosition()(例如,要使用它来保存滚动状态)。如果要查询访问RecyclerView.Adapter内容的位置,则应使用getBindingAdapterPosition()。

或者下面的方法也行:

public void remove(int position) {
        mDataList.remove(position);
        notifyItemRemoved(position);
        if(position != mDataList.size()){ // 如果移除的是最后一个,忽略
            notifyItemRangeChanged(position, mDataList.size() - position);
        }

    }

参考:

RecyclerView里notifyItemRemoved的坑

不推荐使用getAdapterPosition()(getAdapterPosition() is deprecated)