android - RecyclerView 不会删除项目 - 尽管列表具有正确的项目编号
问题描述
我对 recyclerView(使用 GridLayoutManager)有一个奇怪的情况。当我删除一个项目并使用 (notifyItemRemoved 和 notifyItemRangeChanged/notifyDataSetChanged) 刷新它时,它不会删除该项目,而是将其标记为删除(它有点灰显)。如果该项目不是最后一个,那么它有点被删除,但不是真的 - 它就在其他项目之下并且不可见(如果我向这个项目添加额外的视图 - 你可以看到它在那里),但如果它是最后一个你可以看到它变灰了。
这不是我第一次使用 recyclerView,我之前也没有遇到过,但它是第一次使用 GridLayoutManager,所以这可能是原因。
我已经调试了代码,并且在刷新后重新创建recyclerView时,删除onBindViewHolder中的第5个后,可以清楚地看到项目列表包含正确的项目(4)。
这是单击标记图标时的删除功能,它会获得一个 X 图标并出现对话框。
private class DeleteMessageDialog extends MessageDialog {
List<Item> expenses;
public DeleteMessageDialog(String message, List<Item> expenses) {
super(DELETE_CATEGORY, WARNING, message, activity);
this.expenses = expenses;
}
@Override
protected void okPressed() {
DataHelper.getDataHelper(activity).removeItems(expenses);
viewBuilder.refreshItems(DELETE_ITEM);
dismiss();
}
}
刷新方法(我已经硬编码了 4 - 就像我之前使用 notifyDataSetChanged 一样快速而肮脏的解决方案)并根据 Phuc 评论更改了值:
public void refreshItems(Enums.Action action) {
dataHelper.setListOfCategoryItems();
List<Category> categoryItems = Utils.getCategoryItems(Utils.NO_PARENT_PREDICATE);
categoryItemAdapter.updateData(categoryItems);
MonthlyStatistics statistics = DataHelper.getDataHelper(activity).getMonthlyStatistics(Utils.getCurrentDate(PAY));
statBuilder.populateStatistics(statistics.getStatistics().get(category));
if (action == ADD_ITEM)
{
activity.moveToMainPage();
categoryItemAdapter.notifyDataSetChanged();
}
if (action == DELETE_ITEM)
{
categoryItemAdapter.notifyItemRemoved(4);
categoryItemAdapter.notifyItemRangeChanged(4, 1);
}
}
更新数据方法
public void updateData(List<Category> categoryItems) {
this.categoryItems.clear();
this.categoryItems.addAll(categoryItems);
this.parentsAndChildren.clear();
this.parentsAndChildren.putAll(getChildrenAndParents(categoryItems));
}
在调试模式下,onBindViewHolder - 可以看到只剩下正确的 4 个项目
全部完成后就是这样的结果:
如果我删除第三项(不是最后一项),结果如下所示:
我已经搜索了所有互联网,但找不到解决方案,所以我希望在这里发布对您有所帮助。欣赏所有答案。谢谢。
编辑: 正如 Kamal Nayan 建议的那样,如果再次创建适配器并将其放入 recyclerView 确实有效,但我很确定有更好的解决方案,如果有人能找到它,我将不胜感激。
解决方案
您误用了 notifyItemRemoved 和 notifyRangeChanged 的功能。在文档中:
notifyItemRemoved(int 位置)
with position 是被移除的项目的位置。在您的情况下,您要删除第 5 项,因此您应该通过 4,而不是 5。
notifyRangeChanged(int positionStart, itemCount)
- positionStart:第一个改变的项目的位置
- itemCount:已更改的项目数
如果您已经调用过,我认为此方法不是必需的notifyItemRemoved()
,但是您应该为 positionStart 传递 4,为 itemCount 传递 1,因为您只更改了第 5 项。
编辑:我想我在你的代码中看到了另一个问题。每当您删除一个项目时,您都会清除旧列表,然后将新列表传递给适配器。因为附加到适配器的先前列表已被删除并附加了一个新列表,所以您的调用notifyItemRemoved()
没有意义,因为在新列表中,没有任何变化。这会导致您面临意外的回收者视图行为。我建议的解决方案是您修改适配器中的列表,而不是每次删除时都创建新列表。例如deleteItem(int position)
在你的适配器中声明一个方法:
public void deleteItem(int position){
yourList.remove(position);
notifyItemRemoved(position);
}
推荐阅读
- android - 我可以在不发布到 Play 商店的情况下测试动态模块吗?
- angular - Angular 9:TypeScript 中的 i18n
- java - 将布尔值集成到数组参数中
- python - 有没有办法知道一个对象内部是否有一个不可迭代的 NoneType 对象
- javascript - 获取最后一个孩子或孙子的父元素?
- angular - 从Angular 7中的多选下拉列表中选择和取消选择值
- javascript - 使用 Socket.io 可以等待 socket.on('answerToRequest') 吗?
- jquery - JQuery鼠标指针悬停时闪烁
- c# - AspNetIdentity 集成像角色这样的办公室
- python - Python Pandas GroupBy Max Date