Не работает DiffUtill в RecyclerView

Пожалуйста, помогите. Потратил два дня, не могу сам разобраться. Проблема следующая: Есть список: Note.class

public class Note {
int id;
String title;

public Note(int id, String title) {
    this.id = id;
    this.title = title;
}


public int getId() {
    return id;
}

public String getTitle() {
    return title;
}}

Есть DiffUtill

public class NoteDiffCallback extends DiffUtil.Callback {
private final ArrayList<Note> mOldNote;
private final ArrayList<Note> mNewNote;

public NoteDiffCallback(ArrayList<Note> mOldNote, ArrayList<Note> mNewNote) {
    this.mOldNote = mOldNote;
    this.mNewNote = mNewNote;
}

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

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

@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
    return mOldNote.get(oldItemPosition).getId()== mNewNote.get(newItemPosition).getId();
}

@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
  final Note oldNote = mOldNote.get(oldItemPosition);
  final Note newNote = mNewNote.get(newItemPosition);

    return oldNote.getTitle().equals(newNote.getTitle());
}

@Nullable
@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
    // Implement method if you're going to use ItemAnimator
    return super.getChangePayload(oldItemPosition, newItemPosition);
}

Есть Apater:

public class NotesAdapter extends RecyclerView.Adapter<NotesAdapter.NotesViewHolder> {
private ArrayList<Note> notes;

private Context context;
private Listener listener;
private CheckBox checkBox;

public NotesAdapter(ArrayList<Note> notes, Context context) {
    this.notes = notes;
    this.context = context;
}

interface Listener {
    void onClick(int position);
}


@NonNull
@Override
public NotesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.note_layout, parent, false);
    return new NotesViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull NotesViewHolder holder, final int position) {
    final Note note = notes.get(position);

    holder.textViewTitle.setText(note.getTitle());

    holder.textViewTitle.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (listener != null) {
                listener.onClick(position);


            }
        }
    });
}

public void updateNoteListItem2(ArrayList<Note> note) {
    final NoteDiffCallback diffCallback = new NoteDiffCallback(this.notes, note);
    final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);

    this.notes.clear();
    this.notes.addAll(note);
    diffResult.dispatchUpdatesTo(this);

}

@Override
public int getItemCount() {
    return notes.size();
}

public void setListener(Listener listener) {
    this.listener = listener;
}

class NotesViewHolder extends RecyclerView.ViewHolder {
    private TextView textViewTitle;
    public LinearLayout foregroundLayout;

    public NotesViewHolder(@NonNull View itemView) {
        super(itemView);
        textViewTitle = itemView.findViewById(R.id.textViewTitle);
        checkBox = itemView.findViewById(R.id.checkBox);
        foregroundLayout = itemView.findViewById(R.id.animateToEnd);
    }
}

В Адаптере метод updateNoteListItem2 () должен обновлять данные.

В main активности делаю кнопку, которая добавляет данные в Cписок

public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private ArrayList<Note> notes = new ArrayList<>();


NotesAdapter adapter;
EditText editTextTitle;
EditText editTextId;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    recyclerView = findViewById(R.id.recyclerView);
    editTextId = findViewById(R.id.editTextId);
    editTextTitle = findViewById(R.id.editTextTitle);

    if (notes.isEmpty()) {
        notes.add(new Note(0, "Арбуз"));
        notes.add(new Note(1, "Персик"));
        notes.add(new Note(2, "Дыня"));
        notes.add(new Note(3, "Помидор"));
    }
    adapter = new NotesAdapter(notes, this);

    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setAdapter(adapter);
    adapter.setListener(new NotesAdapter.Listener() {
        @Override
        public void onClick(int position) {

        }
    });
}


public void onClick(View view) {
    String title = editTextTitle.getText().toString();
    int id0 = 1+ notes.indexOf(notes.get(notes.size()-1));
    ArrayList<Note> notes2 = new ArrayList<>(notes);
    notes2.add(new Note(id0, title));
    adapter.updateNoteListItem2(notes2);
}

Добавление вроде бы работает. Но как только я хочу удалить данные (в адептере в onClick) указываю следующее:

public class NotesAdapter extends RecyclerView.Adapter<NotesAdapter.NotesViewHolder> {
private ArrayList<Note> notes;
ArrayList<Note> notes2;
/////
 @Override
public void onBindViewHolder(@NonNull NotesViewHolder holder, final int position) {
    final Note note = notes.get(position);

    holder.textViewTitle.setText(note.getTitle());

    holder.textViewTitle.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (listener != null) {
                listener.onClick(position);
                notes2 = new ArrayList<>(notes);
                notes2.remove(position);
                updateNoteListItem2(notes2);

            }
        }
    });
}

Ничего не работает. Первый элемент удаляется корректно. Вместо второго элемента по которому я кликаю, удаляется 3-й элемент. Пожалуйста, подскажите, что я делаю не так? Может использую метод не правильно? Заранее спасибо!


Ответы (1 шт):

Автор решения: tosh17

Все очень просто. В коллекции удалятьнадо не по позиции, а по элементу

notes2.remove(note);

Вы когда удаляете, например 2 элемент, то в коллекции третий элемент становится вторым, но слушатель же вы не переопределяли? и он при вызове будет пытаться удалить третий элемент.

→ Ссылка