0

我现在正在制作一个DiffUtil类来仅更新RecyclerView.

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

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

但是,我认为很难将idor分配unique value给 List,或者代码很乱。

我必须id像这样定义和比较吗?

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

使用 this 不只是比较对象的地址,还比较对象的内容?

作为一个附加问题

DiffUtil.CallBack和 和有什么不一样DiffUtil.ItemCallBack

这是我的代码。

例程模型.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);
    }
}
4

2 回答 2

1

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

常规模型:

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的等号和哈希码。

于 2021-02-01T18:30:21.673 回答
1

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

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

areContentsTheSame()true当且仅当您在上一个回调中返回它们时,才会为两个项目调用。在这里,您必须检查“旧”和“新”模型的视觉表示是否相同。这就是 DiffUtil 知道它是否必须制作“项目更改”动画的方式。

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

现在,谈谈你关于ItemCallback. 正式地,这是来自文档的解释:

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

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

于 2021-02-01T18:17:56.207 回答