相信很多用过RecyclerView的程序员都会感觉到这个控件很强大,的确,它几乎可以实现ListView+GridView的所有功能。强大归强大,但是坑还是有的,今天就来说一下当适配器调用notifyItemRemoved后出现崩溃和代码错乱的问题。
一崩溃、
首先看测试界面
String data = mDatas.get(position); holder.mText.setText(data+position); holder.mText.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mDatas.remove(position); notifyItemRemoved(position); } });
这里总共有五条数据,每行代码的唯一标识为position,当点击position的时候首先删除数组里的对应数据,然后删除适配器里对应的item,问题就出现在这里,当点击测试数据0,删除,没有问题,然后我们点击测试数据4,app直接崩溃,并且,唯一标识position也出现了问题我们看一下debug和运行截图
position=4,mDatas=4,很明显,数组越界,程序崩溃。
当我们调用itemremoved的时候,数组刷新了,item数据没有刷新,删除了item0,之后的数据后面的数字应该集体减1,但是没有减,之后的position没有减,而数组长度却减了1,所以出现了崩溃和数据错乱,这就是问题所在。
position的确定是在适配器的onBindViewHolder这里
@Override public void onBindViewHolder(DemoAdapter.ViewHolder holder, final int position) { String data = mDatas.get(position); holder.mText.setText(data+position); holder.mText.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mDatas.remove(position); notifyItemRemoved(position); } }); }
而当我们删除一个item并且调用了itemremoved的时候,debug,你会发现,onBindViewHolder这个方法没有调用,position没有刷新,所以才出现了我们上面说的数组越界的奔溃和数据错乱的问题。
二解决、
1、可以直接调用notifyDataSetChanged,而不调用itemremoved方法,这就相当于对适配器重新绑定了一次数据。
2、
mDatas.remove(position); notifyItemRemoved(position); notifyItemRangeChanged(position,mDatas.size());
调用了itemRemoved方法之后再调用一次notifyItemRangChanged方法,对删除数据之后的所有数据进行刷新。