简体   繁体   中英

(android) Can I use this code in my DiffUtill implementation?

I am now making a DiffUtil class to update only changed items in the RecyclerView .

I have seen several other sample code.

When comparing two objects, they compared unique values such as id defined in the Model(Data) class in areItemsTheSame() .

However, I think it is difficult to assign an id or unique value to the List, or the code is messy.

Do I have to define and compare id like this?

Do I really need to define a unique Id variable in the Model class that separates each object? Or shouldn't I use simply the equals() ?

Using this Is it not just comparing the address of the object, but also the contents of the object?

As an additional question

What is the difference between DiffUtil.CallBack and DiffUtil.ItemCallBack ?

This is my code.

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);
    }
}

You got wrong the meaning of areItemsTheSame() and areContentsTheSame() callbacks. As you see, there are oldItemPosition and newItemPosition arguments in them. You should use them to compare specific items – not lists themselves.

In areItemsTheSame() you have to check whether model at "old" position in the old list equals a model at "new" position in the new list . This is how DiffUtil knows if it has to make reordering animations.

areContentsTheSame() will be called for two items if and only if you return true for them in the previous callback. Here you have to check whether visual representation of "old" and "new" models is the same. This is how DiffUtil knows if it has to make "item changing" animations.

To compare two models you have to override equals() and hashCode() . There you specify conditions under which you consider two models the same. For example, if they have same routine . I don't the know context of your task so I can't tell you exactly how to implement them, but usually you just compare all fields. Probably adding an id field is a good idea too. Then you can consider models "equal" if they have same id . And in hashCode() you can just return Objects.hash(id) .

Now, speaking about your question about ItemCallback . Formally, here is the explanation from docs:

DiffUtil.Callback serves two roles - list indexing, and item diffing. ItemCallback handles just the second of these, which allows separation of code that indexes into an array or List from the presentation-layer and content specific diffing code.

Practically, ItemCallback just has less methods to implement and is used together with AsyncListDiffer . It's just because missing methods are already implemented under the hood in AsyncListDiffer.

You have to override the equals and hashcodes of your model classes.

RoutineModel:

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));
    }
}

And don't forget to override the equals and hashcode of your RoutineDetailModel .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM