Как получить позицию вставленного элемента с помощью DiffUtil?

Я застрял на довольно простой проблеме в течение некоторого времени. И по какой-то причине я не могу найти ответы на StackOverflow по этому поводу, поэтому я решил обратиться за помощью напрямую.

Проблема проста, у меня есть список объектов Transaction, отсортированных по дате. Я добавляю новую транзакцию в список, а затем прибегаю к ней. Поскольку я не знаю позицию, в которой была добавлена ​​новая транзакция, я пытаюсь использовать DiffUtil, чтобы выяснить это для меня и соответствующим образом обновить содержимое RecyclerView.

Однако результат, который я получаю, действительно странный. По какой-то причине весь список обновляется, и порядок становится полностью перепутанным. Однако исходные данные верны.

Перед обновлением списка: Как получить позицию вставленного элемента с помощью DiffUtil?

После обновления списка: Как получить позицию вставленного элемента с помощью DiffUtil? Вот код, который у меня есть в моем Adapter для добавления нового элемента транзакции.

void addItem(Transaction transaction) {
    ArrayList<Transaction> oldList = new ArrayList<>(transactions);
    transactions.add(transaction);
    Collections.sort(transactions);

    DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffCallback(oldList, transactions), false);
    diffResult.dispatchUpdatesTo(this);
}

И, наконец, вот моя DiffUtilCallback реализация

class DiffCallback extends DiffUtil.Callback {

    private List<Transaction> oldList;
    private List<Transaction> newList;

    public DiffCallback(List<Transaction> oldList, List<Transaction> newList) {
        this.oldList = oldList;
        this.newList = newList;
    }

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

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

    @Override
    public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
        Transaction oldItem = oldList.get(oldItemPosition);
        Transaction newItem = newList.get(oldItemPosition);
        return oldItem.equals(newItem);
    }

    @Override
    public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
        Transaction oldItem = oldList.get(oldItemPosition);
        Transaction newItem = newList.get(oldItemPosition);
        return oldItem.equals(newItem);
    }
}

Вот класс Transaction

public class Transaction implements Comparable<Transaction> {

public String category;
public String description;
public Date date;
public Double amount;

public Transaction(String description, Date date, Double amount) {
    this.category = "";
    this.description = description;
    this.date = date;
    this.amount = amount;
}

public Transaction(String category, String description, Date date, Double amount) {
    this.category = category;
    this.description = description;
    this.date = date;
    this.amount = amount;
}

@Override
public int compareTo(@NonNull Transaction transaction) {
    if (this.category.compareTo(transaction.category) == 0) {
        return this.date.compareTo(transaction.date);
    }
    return this.category.compareTo(transaction.category);
}

@Override
public boolean equals(Object obj) {
    if (!(obj instanceof Transaction)) {
        return false;
    }

    Transaction other = (Transaction)obj;
    return this.category.equals(other.category)
        && this.description.equals(other.description)
        && this.date.equals(other.date)
        && this.amount.equals(other.amount);
}

@Override
public String toString() {
    return description;
}
}

Любая помощь будет оценена. Пожалуйста, дайте мне знать, если для выяснения проблемы требуется дополнительная информация.

пост Transaction класс

Kishore Jethava 17.02.2019 07:28

@KishoreJethava опубликовал

Bazinga 17.02.2019 20:07

Сначала вы сортируете по Transaction.category, а затем по Transaction.date. Из скриншота видно, что ваши транзакции отсортированы по date, но в двух разных наборах. Я подозреваю, что ваш код работает правильно.

2hamed 18.02.2019 07:17

Если вы просто хотите отсортировать по date, удалите части о category в compareTo.

2hamed 18.02.2019 07:18

@HamedMomeni Спасибо за комментарий. category был добавлен, потому что это часть более крупного приложения. Но на предоставленных скриншотах всем транзакциям была присвоена одна и та же категория, так что, вероятно, проблема не в этом.

Bazinga 25.02.2019 02:11
1
5
449
1

Ответы 1

В areContentsTheSame вы должны сравнивать атрибуты Transaction, но вы сравниваете Transaction сам объект.

обновлено areContentsTheSame

@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
    Transaction oldItem = oldList.get(oldItemPosition);
    Transaction newItem = newList.get(oldItemPosition);

    return oldItem.category == newItem.category  && oldItem.description== newItem.description && oldItem.date== newItem.date && oldItem.amount == newItem.amount;
}

Да, для этого я реализовал метод equals внутри Transaction. Пожалуйста, посмотрите код Transaction в моем вопросе.

Bazinga 25.02.2019 02:09
Comparable<Transaction> не требуется для реализации в Transaction
Kishore Jethava 25.02.2019 07:02

Я хочу отсортировать транзакции в порядке их возникновения (по дате) и категории. Вот почему я реализую Comparable. Вы думаете, что это может вызвать проблемы?

Bazinga 26.02.2019 05:30

О, я забыл это. У вас возникает такая же проблема?

Kishore Jethava 26.02.2019 05:36

Другие вопросы по теме