RecyclerView使用DiffUtil,防止在更改时滚动到底部

13

我的recyclerView有问题,特别是滚动方面的问题。

我有一个实时更新的列表,其中某些项目被添加、某些项目被删除,并且根据某个参数进行排序。因此,在列表中最初排在第一位的项目可能会更改其参数,在排序后位于不同的位置。

因此,例如,我的recyclerView专注于最初的项目,但在更改后,当某个项目具有“更好”的参数时,会与该初始项目交换位置。

问题是,在我没有滚动时,我想将焦点放在新项目上,具有“更好”的参数,但我不想在通过触摸滚动时将焦点放在它上面(因此我的触摸不会被滚动到当前列表的第一项所打断)。

因此,我不想在每次更改我的recyclerView数据后强制执行此代码:

recyclerView.scrollToPosition(0);
因为正如我所说的,当我触摸我的recyclerView列表并向下滚动查看其他项目时,我会被此滚动打断,同时列表中会发生变化。
有没有办法解决这个问题?
具体来说,我正在使用来自DiffUtilDiffCallback,以支持在当前recyclerView列表中发生更改时进行动画处理--它会将旧列表与新列表进行比较,并应用所有需要的动画和通知(添加、删除、更改位置)。所以我从来没有调用过
notifyDataSetChanged

这是我的DiffUtil回调:

  public static class DevicesDiffCallback extends DiffUtil.Callback{

    List<DeviceInfo> oldDevices;
    List<DeviceInfo> newDevices;

    public DevicesDiffCallback(List<NexoDeviceInfo> newDevices, List<NexoDeviceInfo> oldDevices) {
        this.newDevices = newDevices;
        this.oldDevices = oldDevices;
    }

    @Override
    public int getOldListSize() {
        return oldDevices != null ? oldDevices.size() : 0;
    }

    @Override
    public int getNewListSize() {
        return newDevices != null ?  newDevices.size() : 0;
    }

    @Override
    public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
        return oldDevices.get(oldItemPosition).getNexoIdentifier().getSerialNumber().equals(newDevices.get(newItemPosition).getNexoIdentifier().getSerialNumber());
    }

    @Override
    public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
        return oldDevices.get(oldItemPosition).equals(newDevices.get(newItemPosition));
    }

    @Override
    public Object getChangePayload(int oldItemPosition, int newItemPosition) {
        return super.getChangePayload(oldItemPosition, newItemPosition);
    }
}

当我获取新数据列表以替换旧数据时,我会在适配器中像这样设置:

 public void setData(List<DeviceInfo> data) {
    DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DevicesDiffCallback(this.mData, data), false);
    diffResult.dispatchUpdatesTo(this);

        mData = data;

}

1
所以你想在新数据到来时滚动到列表顶部,但当用户手动滚动时不要滚动?你能展示一下滚动到新项目的代码吗?它目前有什么问题? - elmorabea
看看这个答案,或许有帮助。 - elmorabea
当用户滚动页面时,我不想自动滚动到顶部。 - K.Os
你想要滚动到哪里呢? :D - elmorabea
是的,但正如评论该答案的人所说,它将始终滚动到新位置。我希望在用户向下滚动查看其他项目时避免这种情况。 - K.Os
显示剩余5条评论
1个回答

2

我不确定这个答案,但是我认为你调用 DiffUtil 的代码不正确。尝试使用以下代码:

public void addItems(List<Recipe> recipeList) {

    List<Recipe> newRecipeList = new ArrayList<>();
    newRecipeList.addAll(this.recipeList);
    newRecipeList.addAll(recipeList);

    DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new RecipeDiffUtilCallback(this.recipeList, newRecipeList));
    this.recipeList.addAll(recipeList);
    diffResult.dispatchUpdatesTo(this);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接