RecyclerView 不会删除项目 - 尽管列表具有正确的项目编号
Posted
技术标签:
【中文标题】RecyclerView 不会删除项目 - 尽管列表具有正确的项目编号【英文标题】:RecyclerView doesn't delete items - although list has correct item number 【发布时间】:2021-07-17 08:16:21 【问题描述】:我对 recyclerView(使用 GridLayoutManager)有一个奇怪的情况。 当我删除一个项目并使用 (notifyItemRemoved 和 notifyItemRangeChanged/notifyDataSetChanged) 刷新它时,它不会删除该项目,而是将其标记为删除(它有点灰显)。如果该项目不是最后一个,那么它有点被删除,但不是真的 - 它就在其他项目下并且不可见(如果我向这个项目添加额外的视图 - 你可以看到它在那里),但如果它是最后一个你可以看到它是灰色的。
这不是我第一次使用recyclerView,我之前也没有遇到过,但它是第一次使用GridLayoutManager,所以这可能是原因。
我已经调试过代码,刷新后重新创建recyclerView时,删除onBindViewHolder中的第5个后,可以清楚地看到List of items包含正确的项目(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);
updateData 方法
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 确实有效,但我很确定有更好的解决方案,如果有人能找到它,我将不胜感激。
【问题讨论】:
尝试重新设置适配器? @KamalNayan 我一直在避免这个解决方案,但是是的,再次设置适配器是可行的,但我很确定这不是正确的做法,因为我们确实有所有的通知方法要做只是。不过感谢您的建议。 如果您想为此分享一个演示,我们可以彻底了解一下,因为这是一种奇怪的行为 @Zain 这几乎是一个带有屏幕截图的演示。屏幕截图的顺序正确。单击某个图标后,将出现删除消息。通过点击DELETE按钮,你看到的结果.. 【参考方案1】:您误用了 notifyItemRemoved 和 notifyRangeChanged 的功能。在文档中:
notifyItemRemoved(int 位置)
with position 是项目被移除的位置。在您的情况下,您要删除第 5 项,因此您应该传递 4 而不是 5。
positionStart:已更改的第一项的位置 itemCount:已更改的项目数notifyRangeChanged(int positionStart, itemCount)
如果你已经调用了notifyItemRemoved()
,我认为这个方法是不必要的,但是你应该为 positionStart 传递 4,为 itemCount 传递 1,因为你只更改了第 5 个项目。
编辑:我想我在您的代码中发现了另一个问题。每当您删除一个项目时,您都会清除旧列表,然后将新列表传递给适配器。因为附加到适配器的先前列表已被删除并附加了一个新列表,所以您对 notifyItemRemoved()
的调用没有意义,因为在新列表中,没有任何变化。这会导致您面临意外的回收者视图行为。我建议的解决方案是您修改适配器中的列表,而不是每次删除时都创建新列表。例如在你的适配器中声明一个方法deleteItem(int position)
:
public void deleteItem(int position)
yourList.remove(position);
notifyItemRemoved(position);
【讨论】:
您对这两种方法的滥用是正确的,谢谢。我解决了这个问题,不幸的是它不能解决我的问题。 Kamal 建议的解决方案确实有效,但我很确定这不是正确的做法。 是的,不需要设置新的适配器。请看我编辑的答案 虽然我认为列表是同一个列表(当我从传递给状态列表的列表中添加项目时),我做了你的建议(从列表中明确删除项目而不添加其他列表中的项目),仍然得到相同的结果。 是的,对不起,你也许是对的。但至少我的方式会切断整个clear()
和addAll()
。关于问题,很奇怪。是不是把GridLayout换成别的布局管理器(即:LinearLayoutManager),问题还存在吗?
是的,我现在已将其更改为线性。同样的问题。对我来说似乎是魔法。现在唯一可行的解决方案是重新加载适配器,我试图避免这种情况。以上是关于RecyclerView 不会删除项目 - 尽管列表具有正确的项目编号的主要内容,如果未能解决你的问题,请参考以下文章