首页 > 解决方案 > 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 确实有效,但我很确定有更好的解决方案,如果有人能找到它,我将不胜感激。

标签: androidandroid-recyclerviewgridlayoutmanager

解决方案


您误用了 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);
}

推荐阅读