RecyclerView添加和删除操作notifyDataSetChanged依旧会导致item混乱的解决办法

匿名 (未验证) 提交于 2019-12-03 00:22:01

记录一个自己犯的蠢问题


@Override     public void onBindViewHolder(final ViewHolder holder, int position) {         final int pos = position;           if(!holder.add.hasOnClickListeners()){             holder.add.setOnClickListener(new View.OnClickListener() {                 @Override                 public void onClick(View view) {                     infoList.add(pos,new TeacherChangeGradeInfo());                     Log.e("add POS:",pos+",size:"+infoList.size());                     notifyItemInserted(pos);//通知演示插入动画                     notifyItemRangeChanged(pos,infoList.size()-pos);//通知数据与界面重新绑定                 }             });              holder.delete.setOnClickListener(new View.OnClickListener() {                 @Override                 public void onClick(View view) {                     infoList.remove(pos);                     Log.e("delete POS:",pos+",size:"+infoList.size());                     notifyDataSetChanged(); //                    notifyItemRemoved(pos);//通知演示插入动画 //                    notifyItemRangeChanged(0,infoList.size());//通知数据与界面重新绑定                 }             });                      }     }

我要做到的是点击item上的添加和删除按钮能够正确添加和删除item项,但在实际中item位置混乱,经常越界报错

无论是使用

notifyItemInserted(pos);//通知演示插入动画 notifyItemRangeChanged(pos,infoList.size()-pos);//通知数据与界面重新绑定
还是
notifyDataSetChanged();

都是一样的效果,几番查找似乎找到了解决方案,onBindViewHolder方法的position不是实时更新的,遂改为

final int pos = holder.getLayoutPosition();

怀着期待再次调试,又崩了,并且问题还是一样。

在stackoverflow上都没有找到方案,万念俱灰。

根据“大多数人在网上找不到解决方案的问题只有两种,一种是闭源的,一种是弱智的”法则,我终于找到了真相

final int pos = holder.getLayoutPosition();

pos是在onClick方法外调用的,也就是说对于同一ViewHolder的pos值在创建后其实一直没有变……

最后解决方案,在onClick方法内调用此方法

public void onClick(View view) {                     final int pos = holder.getLayoutPosition();                     infoList.add(pos,new TeacherChangeGradeInfo());                     Log.e("add POS:",pos+",size:"+infoList.size());                     notifyDataSetChanged(); //                    notifyItemInserted(pos);//通知演示插入动画 //                    notifyItemRangeChanged(pos,infoList.size()-pos);//通知数据与界面重新绑定                 }

就解决了问题。

另外,使用notifyDataSetChanged和使用notifyItemInserted/notifyItemRemoved+notifyItemRangeChanged都可以,但是后者有动画,并且刷新的内容比较少,故推荐。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!