Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/205.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android RecyclerView通知XXX_Android_Android Recyclerview_Android Adapter_Notifydatasetchanged - Fatal编程技术网

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