问题
公司项目中有遇到一个问题,需要做多条目的删除,如图所示:
分析
如果是每次删除一条的时候,可以使用系统自带的方法:
//取消收藏并且要刷新适配器
public void cancleCollect2(int position) {
testBeen.remove(i);
notifyItemRemoved(i);
notifyItemRangeChanged(i,testBeen.size()-i);
}
还有点要记住, notifyItemRangeChanged(i,testBeen.size()-i);在删除单条目的时候一定要加,如果不加的话无法保证删除之后数据顺序同步问题,这个方法最后还是调用:
public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
// fallback to onItemRangeChanged(positionStart, itemCount) if app
// does not override this method.
onItemRangeChanged(positionStart, itemCount);
}
这个方法里面有个参数Object payload,这个参数作用是可以保证在局部刷新的过程中对于设置的某一个view不出现闪动效果,接下来介绍该如何使用这个参数。payload这个参数默认就是传的null,意思对item全局刷新,比如对于一个图片不刷新的情况;
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.test.setText(testBeen.get(position).getNum() + "");
//这里可以刷新图片的情况,看实际的使用情况
}
@Override
public void onBindViewHolder(ViewHolder holder, int position, List<Object> payloads) {
//这个千万要去掉,不然没作用
// super.onBindViewHolder(holder, position, payloads);
if(payloads.isEmpty()) {
//如果没有想不做刷新的就调用第一个重写方法
onBindViewHolder(holder,position);
}else {
//对于哪个控件想刷新的,例如只有文字,没有图片
holder.test.setText(testBeen.get(position).getNum() + "");
}
}
当然还有其他方式解决局部刷新出现的问题:
ItemAnimator animator = recyclerView.getItemAnimator();
if (animator instanceof SimpleItemAnimator) {
((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
}
上述方法是最简单的方式,对于item的刷新确实是因为系统动画的原因,当然还可以设置动画的时间来控制:
recyclerView.getAnimation().setDuration(0);
recyclerView.getItemAnimator().setSupportsChangeAnimations(false);
当然对于局部刷新或者对于数据更新还有很多知识需要慢慢了解,当然本文主要是解决多条目删除问题,当出现删除多条的时候,我第一个想法是用循环的方式删除如下:
//取消收藏并且要刷新适配器
public void cancleCollect2() {
//一次只能有一个线程进入
if (testBeen != null) {
for (int i = 0; i < testBeen.size(); i++) {
if (testBeen.get(i).isChecked()) {
testBeen.remove(i);
notifyItemRemoved(i);
notifyItemRangeChanged(i,testBeen.size()-i);
}
}
}
}
但是出现的重大的问题,只要你选多条,每次都不能删除完全,需要多次删除,之前我同事说要用翻页删除数据,但是我认为不用,出现这种情况,我第一时间是想到的解决问题,最后想到一种方式:
解决
//取消收藏并且要刷新适配器
public synchronized void cancleCollect() {
//筛选出需要删除的item,然后一起删除再刷新适配器
List<TestBean> testBeen2 = new ArrayList<>();
if (testBeen != null) {
for (int i = 0; i < testBeen.size(); i++) {
synchronized (this){
if (testBeen.get(i).isChecked()) {
testBeen2.add(testBeen.get(i));
}
}
}
testBeen.removeAll(testBeen2);
notifyDataSetChanged();
}
}
对于要删除的数据新建一个集合,当循环遍历完成就把要删除数据的集合从总数据集合中移除,最后发现这样是可以的。当到这时,我思考为什么一次性移除没问题,但是每次移除就会有问题,肯定你们也想到了,莫非是因为线程数据同步的问题,我查看了RecyclerView源码的删除插入等方法还有刷新方法都没有做线程同步问题,里面只是使用了观察者模式,对于这个问题我想肯定还有更好的方法解决。
总结
如果本文说的哪里有问题,希望大家指正,毕竟本人技术有限,对于开发也才刚接触没多久,或者有更好的意见希望加我微信告知,谢谢!