(android) 我可以在我的 DiffUtill 实现中使用这个代码吗?

问题描述

我现在正在创建一个 DiffUtil 类来仅更新 RecyclerView 中已更改的项目。

我看过其他几个示例代码。

在比较两个对象时,他们比较了Model(Data)areItemsTheSame()类中定义的id等唯一值。

不过我觉得给List赋值一个id或者unique value比较困难,或者代码很乱。

我是否必须像这样定义和比较 id

我真的需要在分隔每个对象的 Model class 中定义一个唯一的 Id 变量吗? 或者我不应该只使用 equals() 吗?

使用这个不就是比较对象的地址,还比较对象的内容吗?

作为附加问题

DiffUtil.CallBackDiffUtil.ItemCallBack 有什么区别?

这是我的代码。

RoutineModel.java

public class RoutineModel {
    private ArrayList<RoutineDetailModel> routineDetailModels;
    private String routine;

    public RoutineModel(ArrayList<RoutineDetailModel> items,String routine) {
        this.routine = routine;
        this.routineDetailModels = items;
    }

    public ArrayList<RoutineDetailModel> getDetailItemList() {
        return routineDetailModels;
    }

    public int getDetailItemSize() {
        return routineDetailModels.size();
    }

    public String getRoutine() {
        return routine;
    }

    public void setRoutine(String routine) {
        this.routine = routine;
    }
}

RoutineDiffUtil.java

public class RoutineDiffUtil extends DiffUtil.Callback {
    private final List<RoutineModel> oldRoutineList;
    private final List<RoutineModel> newRoutineList;

    public RoutineDiffUtil(ArrayList<RoutineModel> oldRoutineList,ArrayList<RoutineModel> newRoutineList) {
        this.oldRoutineList = oldRoutineList;
        this.newRoutineList = newRoutineList;
    }

    @Override
    public int getOldListSize() {
        return oldRoutineList.size();
    }

    @Override
    public int getNewListSize() {
        return newRoutineList.size();
    }

    @Override
    public boolean areItemsTheSame(int oldItemPosition,int newItemPosition) {
        return oldRoutineList.equals(newRoutineList);
    }

    @Override
    public boolean areContentsTheSame(int oldItemPosition,int newItemPosition) {
        return oldRoutineList.equals(newRoutineList);
    }
}

解决方法

您弄错了 areItemsTheSame()areContentsTheSame() 回调的含义。如您所见,其中有 oldItemPositionnewItemPosition 参数。您应该使用它们来比较特定项目 - 而不是列表本身。

areItemsTheSame()中,您必须检查旧列表中“旧”位置的模型是否等于新列表中“新”位置的模型.这就是 DiffUtil 知道它是否必须制作重新排序动画的方式。

当且仅当您在前一个回调中为它们返回 areContentsTheSame() 时,才会为两个项目调用

true。在这里,您必须检查“旧”和“新”模型的视觉表示是否相同。这就是 DiffUtil 知道它是否必须制作“项目更改”动画的方式。

要比较两个模型,您必须覆盖 equals()hashCode()。在那里您可以指定将两个模型视为相同的条件。例如,如果它们具有相同的 routine。我不知道你的任务的上下文,所以我不能确切地告诉你如何实现它们,但通常你只是比较所有领域。可能添加一个 id 字段也是一个好主意。然后,如果模型具有相同的 id,则您可以将模型视为“相等”。而在 hashCode() 中,您只需返回 Objects.hash(id)

现在,谈谈您关于 ItemCallback 的问题。正式地,这里是文档的解释:

DiffUtil.Callback 有两个作用 - 列表索引和项目差异。 ItemCallback 只处理其中的第二个,这允许将索引到数组或列表的代码与表示层和内容特定的差异代码分开。

实际上,ItemCallback 只是需要实现的方法较少,并且与 AsyncListDiffer 一起使用。这只是因为缺少的方法已经在 AsyncListDiffer 中实现了。

,

您必须覆盖模型类的等号和哈希码。

例程模型:

class RoutineModel {
    private ArrayList<RoutineDetailModel> routineDetailModels;
    private String            routine;

    public RoutineModel(ArrayList<RoutineDetailModel> items,String routine) {
        this.routine = routine;
        this.routineDetailModels = items;
    }

    public ArrayList<RoutineDetailModel> getDetailItemList() {
        return routineDetailModels;
    }

    public int getDetailItemSize() {
        return routineDetailModels.size();
    }

    public String getRoutine() {
        return routine;
    }

    public void setRoutine(String routine) {
        this.routine = routine;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        RoutineModel that = (RoutineModel) o;
        return Objects.equals(routineDetailModels,that.routineDetailModels) &&
            Objects.equals(routine,that.routine);
    }

    @Override
    public int hashCode() {
        return Objects.hash(routineDetailModels,routine);
    }
}

RoutineDiffUtil:

public class RoutineDiffUtil extends DiffUtil.Callback {
    private final List<RoutineModel> oldRoutineList;
    private final List<RoutineModel> newRoutineList;

    public RoutineDiffUtil(ArrayList<RoutineModel> oldRoutineList,ArrayList<RoutineModel> newRoutineList) {
        this.oldRoutineList = oldRoutineList;
        this.newRoutineList = newRoutineList;
    }

    @Override
    public int getOldListSize() {
        return oldRoutineList.size();
    }

    @Override
    public int getNewListSize() {
        return newRoutineList.size();
    }

    @Override
    public boolean areItemsTheSame(int oldItemPosition,int newItemPosition) {
        return oldRoutineList.get(oldItemPosition).getRoutine().equals(newRoutineList.get(newItemPosition).getRoutine());
    }

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

并且不要忘记覆盖RoutineDetailModel的equals和hashcode。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...