RecyclerView 总是从视图中删除最后一个项目,并且在删除位置 0 的项目时出错

RecyclerView always removes the last item from view and errors when removing item at position 0

过去 2 天我一直在与 RecyclerView 作斗争。与以往不同,我想要滑动关闭功能。

我关注了 this guide

这里我实现的唯一区别是我没有使用预定义数组进行输入,而是使用 API 响应来填充数据。一切似乎都很好,当我打开 recyclerview 时,项目会按应有的方式填充。按照他们应该的顺序。

这就是乐趣的开始。如果我尝试滑动以关闭第一项,我会收到 IndexOutOfBounds 错误。太可爱了,搜索我发现有些选择在第一个列表的基础上设置一个新的列表,删除项目,然后将原来的列表重新分配给新的列表。 notifyDataSetChanged() 完成后。没有更多的错误,但没有回收站视图的动画将第二个项目带到列表的顶部。任何时候调用 notifyDataSetChanged() 列表都不会移动。我向下滚动并向上滚动,项目又回来了。或者我是这么想的。

玩了一会儿后,我注意到虽然第一项中的信息看起来是原始的第一项,但它得到了列表中第二项的 ID,视图中的最后一项是现在不见了。

这是一个例子:

  1. text = Fox id = a
  2. text = 狗 id = b
  3. text=猪id=c

我从列表中滑动关闭 1,这就是 UI 显示的内容

  1. text=狐狸id=b
  2. text = 狗 id = c

这里嵌入了很多代码,尝试这样做会抛出错误,要点在这里 https://gist.github.com/baggednismo/2840d0f777438d29673bc29096153970

尝试从您的适配器中删除 setHasStableIds(true) 和覆盖的 getItemId()

你告诉 RecyclerView 第 nth 视图将始终代表列表中的相同项目,当你删除其中一个时它会变得不安项目。

(我刚刚用 setHasStableIds(true) 尝试了一个非常简化的示例,并遇到了类似的异常;当我删除它和 getItemId() 时它工作正常)

请注意,您调用 notifyItemDeleted() 比替换整个列表更可取,但如果您确实想要或需要替换整个列表,您应该考虑使用 DiffUtil 来确定和制作对列表进行适当的更改,如果相同的项目仍然存在,它将执行所有很酷的动画。

如果你想看我的例子,它在 https://gist.github.com/javadude/dec1862b075338790f023b42e01fd953(但它在 kotlin 中)

@Scott Stanchfield 的输入非常正确。他的评论和回答中提到的更改清理了视图,以帮助我找到与实际视图相关的问题。这些建议仍在实施,并且是解决方案的一部分。

onBindViewHolder() 根据原始 API 响应顺序而不是 recyclerview 正在处理的列表顺序创建其正在创建行项目的项目视图。每次新项目出现在滚动列表中时都会调用 onBindViewHolder(),这就是问题所在。这在列表的第一个 inflation 上工作正常,但是一旦项目被删除并滚动回顶部,第一个项目似乎是被忽略的项目。

原文:

KitchenOrdersResponse.Item mItem = mKitchenOrdersResponse.getItems().get(i);

分辨率:

KitchenOrdersResponse.Item mItem = mItems.get(i);