Android RecyclerView通知XXX
最近从Android RecyclerView通知XXX,android,android-recyclerview,android-adapter,notifydatasetchanged,Android,Android Recyclerview,Android Adapter,Notifydatasetchanged,最近从notifyDataSetChanged切换到notifyItemInserted/Changed/Removed,以保留动画 我陷入了这种境地。我的适配器列表最初是: A B C D 然后合并A、B和C,在最后一个位置插入一个新的E项: A E 我想我可以通知索引1(B)被删除,索引2(C)被删除,索引3(D)被删除,然后新的索引1(E)被插入,但我不知道从哪里来的一个例外是: 检测到不一致。视图保持器适配器无效 位置视图持有者 因此,我认为可能是由于对索引1发出了两次通知而引起了
notifyDataSetChanged
切换到notifyItemInserted/Changed/Removed
,以保留动画
我陷入了这种境地。我的适配器列表最初是:
A
B
C
D
然后合并A、B和C,在最后一个位置插入一个新的E项:
A
E
我想我可以通知索引1(B)被删除,索引2(C)被删除,索引3(D)被删除,然后新的索引1(E)被插入,但我不知道从哪里来的一个例外是:
检测到不一致。视图保持器适配器无效
位置视图持有者
因此,我认为可能是由于对索引1发出了两次通知而引起了问题,因此我将其更改为通知索引1(B)更改为E,通知索引2(C)已删除,通知索引3(D)已删除,但引发了相同的异常,使我没有更多的选项
在这种情况下,什么是正确的方法?不要让问题没有答案,以防其他人也有同样的问题 支持库24.2作为一个有用的类发布,用于计算两组项目之间的差异 示例代码可以是这样的(创建两个列表并按下按钮交换适配器中的项目)。DiffUtil.diffesult将处理所有
notify
调用
final List<RecyclerObject> list = new ArrayList<>();
list.add(new RecyclerObject("A"));
list.add(new RecyclerObject("B"));
list.add(new RecyclerObject("C"));
list.add(new RecyclerObject("D"));
final TestAdapter adapter = new TestAdapter(list);
recycler.setAdapter(adapter);
final List<RecyclerObject> newList = new ArrayList<>();
newList.add(new RecyclerObject("A"));
newList.add(new RecyclerObject("E"));
final View button = findViewById(R.id.mainButton);
button.setOnClickListener(v -> {
adapter.setList(newList);
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffCallback(list, newList));
diffResult.dispatchUpdatesTo(adapter);
});
final List=new ArrayList();
添加(新的回收对象(“A”);
添加(新的回收对象(“B”);
添加(新的回收对象(“C”);
添加(新的回收对象(“D”);
最终测试适配器=新测试适配器(列表);
回收器。设置适配器(适配器);
最终列表newList=newarraylist();
添加(新的回收对象(“A”);
添加(新的回收对象(“E”);
最终视图按钮=findViewById(R.id.Main按钮);
按钮。setOnClickListener(v->{
adapter.setList(newList);
DiffUtil.diffesult diffesult=DiffUtil.calculateDiff(新DiffCallback(list,newList));
dispatchUpdatesTo(适配器);
});
Diffcallback是自己创建的类,实现可以如下所示。(删除不必要的代码以提高可读性)
public类DiffCallback扩展了DiffUtil.Callback{
DiffCallback(最终列表、最终列表、新列表){
this.list=列表;
this.newList=newList;
}
@凌驾
public int getOldListSize(){
返回list.size();
}
@凌驾
public int getNewListSize(){
返回newList.size();
}
@凌驾
公共布尔值是相同的内容(final int oldItemPosition,final int newItemPosition){
返回list.get(oldItemPosition).title.equals(newList.get(newItemPosition).title);
}
}
还有一种不那么花哨的方法:如果我们可以保证支持适配器的项目是“稳定的”,并且同一项目始终具有相同的标识符,那么recycler.adapter允许使用
setHasStableIds
选项。这样,即使只使用notifyDatasetChanged
(通常会终止动画)也能正确处理动画。需要重写函数getItemId()
,以便在其他人有相同问题的情况下,不允许提问而不回答
支持库24.2作为一个有用的类发布,用于计算两组项目之间的差异
示例代码可以是这样的(创建两个列表并按下按钮交换适配器中的项目)。DiffUtil.diffesult将处理所有notify
调用
final List<RecyclerObject> list = new ArrayList<>();
list.add(new RecyclerObject("A"));
list.add(new RecyclerObject("B"));
list.add(new RecyclerObject("C"));
list.add(new RecyclerObject("D"));
final TestAdapter adapter = new TestAdapter(list);
recycler.setAdapter(adapter);
final List<RecyclerObject> newList = new ArrayList<>();
newList.add(new RecyclerObject("A"));
newList.add(new RecyclerObject("E"));
final View button = findViewById(R.id.mainButton);
button.setOnClickListener(v -> {
adapter.setList(newList);
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffCallback(list, newList));
diffResult.dispatchUpdatesTo(adapter);
});
final List=new ArrayList();
添加(新的回收对象(“A”);
添加(新的回收对象(“B”);
添加(新的回收对象(“C”);
添加(新的回收对象(“D”);
最终测试适配器=新测试适配器(列表);
回收器。设置适配器(适配器);
最终列表newList=newarraylist();
添加(新的回收对象(“A”);
添加(新的回收对象(“E”);
最终视图按钮=findViewById(R.id.Main按钮);
按钮。setOnClickListener(v->{
adapter.setList(newList);
DiffUtil.diffesult diffesult=DiffUtil.calculateDiff(新DiffCallback(list,newList));
dispatchUpdatesTo(适配器);
});
Diffcallback是自己创建的类,实现可以如下所示。(删除不必要的代码以提高可读性)
public类DiffCallback扩展了DiffUtil.Callback{
DiffCallback(最终列表、最终列表、新列表){
this.list=列表;
this.newList=newList;
}
@凌驾
public int getOldListSize(){
返回list.size();
}
@凌驾
public int getNewListSize(){
返回newList.size();
}
@凌驾
公共布尔值是相同的内容(final int oldItemPosition,final int newItemPosition){
返回list.get(oldItemPosition).title.equals(newList.get(newItemPosition).title);
}
}
还有一种不那么花哨的方法:如果我们可以保证支持适配器的项目是“稳定的”,并且同一项目始终具有相同的标识符,那么recycler.adapter允许使用
setHasStableIds
选项。这样,即使只使用notifyDatasetChanged
(通常会终止动画)也能正确处理动画。需要重写函数getItemId()
您尝试过DiffUtils吗?老实说,我不知道它是什么…只是用Google搜索…它会弄乱动画,就像使用notifyDataSetChanged一样:(不应该,DiffUtils很尊重动画。无论如何,如果你能保证稳定的ID,你可以使用notifyDataSetChanged的ID。你试过DiffUtils吗?老实说,我不知道它是什么…只是用谷歌搜索…它会弄乱动画,就像使用notifyDataSetChanged一样。)(不应该,DiffUtils很好地尊重动画。无论如何,如果你能保证稳定的ID,你也可以使用notifyDataSetChanged