Ganti notifyDataSetChanged dengan DiffUtil dengan Databinding, LiveData di MVVM

Sampel Google untuk aplikasi TODO menggunakan MVVM, penyatuan data, LiveData, dan notifyDataSetChanged(). Saya ingin mengganti ini dengan DiffUtil. Sampel memuat ulang data dalam fungsi fragmen onResume.

TasksFragment.java

Memuat ulang seluruh dataSet dalam fungsi onResume.

@Override
public void onResume() {
    super.onResume();
    mTasksViewModel.start();
}

tasks_frag.xml

<ListView
    android:id="@+id/tasks_list"
    app:items="@{viewmodel.items}"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

Adaptor

public class TasksAdapter extends BaseAdapter {
    private final TasksViewModel mTasksViewModel;
    private List<Task> mTasks;

    private void setList(List<Task> tasks) {
        mTasks = tasks;
        notifyDataSetChanged();
    }
}

TasksListBindings.java

public class TasksListBindings {

    @SuppressWarnings("unchecked")
    @BindingAdapter("app:items")
    public static void setItems(ListView listView, List<Task> items) {
        TasksAdapter adapter = (TasksAdapter) listView.getAdapter();
        if (adapter != null)
        {
            adapter.setData(items);
        }
    }
}

Saya sudah menerapkan DiffUtil sebagai pengganti notifyDataSetChanged seperti ini.

protected void setList(List<Item> tasks) {
    Log.d("customeee", "mTasks setList");
    final ItemsDiffCallback diffCallback = new ItemsDiffCallback(this.mTasks, tasks);
    final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);

    diffResult.dispatchUpdatesTo(this);
    this.mTasks.clear();
    this.mTasks.addAll(tasks);

}

Namun yang terjadi adalah apa pun yang saya lakukan, fungsi areContentsTheSame selalu menghasilkan nilai true. Jika saya memaksakan kesalahan, pembaruan berfungsi dengan baik.

@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
    final Item oldItem = mOldList.get(oldItemPosition);
    final Item newItem = mNewList.get(newItemPosition);

    Log.d("customeee", oldItem.getNote() + " newItem: "+newItem.getNote());
    Log.d("customeee", "New == old? "+mOldList.equals(mNewList));

    return oldItem.getNote().equals(newItem.getNote());
}

oldItem.getNote() dan newItem.getNote() keduanya mengembalikan nilai baru. Saya pikir ini ada hubungannya dengan referensi jika objek daftar sebagai Daftar Lama.sama dengan(Daftar Baru).


person S. Gissel    schedule 10.10.2019    source sumber
comment
Anda dapat melihat contoh ini di sini github.com/MMRBD/Note-MVVM-Room-LiveData   -  person Moklesur Rahman    schedule 10.10.2019
comment
@MMR referensi Anda banyak membantu saya. Di bawah ini saya memposting jawaban yang akhirnya membantu saya memperbaiki masalah ini.   -  person S. Gissel    schedule 15.10.2019
comment
saya juga menghadapi masalah yang sama baru-baru ini. Meskipun daftar adaptor Anda adalah ArrayList baru‹› tetapi ketika Anda melakukan add() atau addAll() pada dasarnya Anda menambahkan objek yang sama ke daftar baru. Jadi jika Anda mengubah item daftar dari daftar adaptor atau model tampilan, perubahan akan terlihat di kedua daftar karena kedua daftar berisi objek yang sama. Apa yang saya lakukan adalah meneruskan peta HashMap‹Integer, Object› ke adaptor saya. position memberitahukan item posisi mana yang telah berubah dan Objek memiliki apa yang telah berubah dan menggunakannya di dalam areContentsTheSame(). Sejauh ini tidak dapat menemukan cara yang bersih.   -  person Shikhar Deep    schedule 20.11.2020
comment
Pendekatan lengkap di sini: stackoverflow.com/questions/57876118/   -  person Shikhar Deep    schedule 20.11.2020


Jawaban (1)


Solusi:

Daripada menggunakan DiffUtil secara langsung, Google datang dengan solusi baru - AsyncListDiffer. Contoh kode kecil ini dari referensi kelas membawa jawabannya.

Saya juga melewatkan sesuatu. Di sampel Google mereka membuat objek baru untuk disimpan ke repositori. Yang dibutuhkan:

item = new Item(title.getValue(), description.getValue(), mTaskId, mItemCompleted);
updateItem(item);

Apa yang saya lakukan hanyalah memperbarui objek yang ada dengan nilai-nilai baru yang diharapkan berubah:

this.item.getValue().setFavorite(favorite.getValue());
this.item.getValue().setNote(note.getValue());
updateTask(item.getValue());

Mengikuti panduan implementasi untuk AsyncListDiffer dan aplikasi contoh Google membantu saya mengatasi masalah ini.

person S. Gissel    schedule 15.10.2019