Не работает 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 шт):
Все очень просто. В коллекции удалятьнадо не по позиции, а по элементу
notes2.remove(note);
Вы когда удаляете, например 2 элемент, то в коллекции третий элемент становится вторым, но слушатель же вы не переопределяли? и он при вызове будет пытаться удалить третий элемент.