Mencoba mencari tahu apa masalahnya dengan memperbarui RecyclerView
Adaptor.
Setelah saya mendapatkan Daftar produk baru, saya mencoba untuk:
Perbarui
ArrayList
dari fragmen tempatrecyclerView
dibuat, atur data baru ke adaptor, lalu panggiladapter.notifyDataSetChanged()
; tidak bekerja.Buat adaptor baru, seperti yang dilakukan orang lain, dan itu berhasil untuk mereka, tetapi tidak ada perubahan untuk saya:
recyclerView.setAdapter(new RecyclerViewAdapter(newArrayList))
Buat metode di
Adapter
mana memperbarui data sebagai berikut:public void updateData(ArrayList<ViewModel> viewModels) { items.clear(); items.addAll(viewModels); notifyDataSetChanged(); }
Lalu saya memanggil metode ini setiap kali saya ingin memperbarui daftar data; tidak bekerja.
Untuk memeriksa apakah saya dapat memodifikasi recyclerView dengan cara apa pun, dan saya mencoba menghapus setidaknya satu item:
public void removeItem(int position) { items.remove(position); notifyItemRemoved(position); }
Segalanya tetap seperti itu.
Ini Adaptor saya:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> implements View.OnClickListener {
private ArrayList<ViewModel> items;
private OnItemClickListener onItemClickListener;
public RecyclerViewAdapter(ArrayList<ViewModel> items) {
this.items = items;
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycler, parent, false);
v.setOnClickListener(this);
return new ViewHolder(v);
}
public void updateData(ArrayList<ViewModel> viewModels) {
items.clear();
items.addAll(viewModels);
notifyDataSetChanged();
}
public void addItem(int position, ViewModel viewModel) {
items.add(position, viewModel);
notifyItemInserted(position);
}
public void removeItem(int position) {
items.remove(position);
notifyItemRemoved(position);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
ViewModel item = items.get(position);
holder.title.setText(item.getTitle());
Picasso.with(holder.image.getContext()).load(item.getImage()).into(holder.image);
holder.price.setText(item.getPrice());
holder.credit.setText(item.getCredit());
holder.description.setText(item.getDescription());
holder.itemView.setTag(item);
}
@Override
public int getItemCount() {
return items.size();
}
@Override
public void onClick(final View v) {
// Give some time to the ripple to finish the effect
if (onItemClickListener != null) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
onItemClickListener.onItemClick(v, (ViewModel) v.getTag());
}
}, 0);
}
}
protected static class ViewHolder extends RecyclerView.ViewHolder {
public ImageView image;
public TextView price, credit, title, description;
public ViewHolder(View itemView) {
super(itemView);
image = (ImageView) itemView.findViewById(R.id.image);
price = (TextView) itemView.findViewById(R.id.price);
credit = (TextView) itemView.findViewById(R.id.credit);
title = (TextView) itemView.findViewById(R.id.title);
description = (TextView) itemView.findViewById(R.id.description);
}
}
public interface OnItemClickListener {
void onItemClick(View view, ViewModel viewModel);
}
}
Dan saya memulai RecyclerView
sebagai berikut:
recyclerView = (RecyclerView) view.findViewById(R.id.recycler);
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 5));
adapter = new RecyclerViewAdapter(items);
adapter.setOnItemClickListener(this);
recyclerView.setAdapter(adapter);
Jadi, bagaimana cara saya benar-benar memperbarui data adaptor untuk menampilkan item yang baru diterima?
Pembaruan: masalahnya adalah tata letak tempat gridView tampak sebagai berikut:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:tag="catalog_fragment"
android:layout_height="match_parent">
<FrameLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"/>
<ImageButton
android:id="@+id/fab"
android:layout_gravity="top|end"
style="@style/FabStyle"/>
</FrameLayout>
</LinearLayout>
Lalu saya baru saja menghapus LinearLayout
dan menjadikan FrameLayout
layout orangtua.
sumber
items.clear(); items.addAll(newItems);
adalah pola yang jelek. Jika Anda benar-benar perlu menyalin defensif di sini,items = new ArrayList(newItems);
akan kurang jelek.Jawaban:
Saya bekerja dengan RecyclerView dan baik menghapus maupun memperbarui berfungsi dengan baik.
1) HAPUS: Ada 4 langkah untuk menghapus item dari RecyclerView
Baris kode ini cocok untuk saya.
2) MEMPERBARUI DATA: Satu-satunya hal yang harus saya lakukan adalah
Anda harus melakukan semua ini dalam kode Actvity / Fragment tidak dalam kode Adapter RecyclerView.
sumber
recycler.removeViewAt(position);
(atau lebih tepatnyarecycler.removeAllViews()
) adalah yang paling penting.Ini adalah jawaban umum untuk pengunjung masa depan. Berbagai cara untuk memperbarui data adaptor dijelaskan. Proses ini mencakup dua langkah utama setiap kali:
Sisipkan satu item
Tambahkan "Babi" di indeks
2
.Sisipkan beberapa item
Masukkan tiga hewan lagi di indeks
2
.Hapus satu item
Hapus "Babi" dari daftar.
Hapus beberapa item
Hapus "Unta" dan "Domba" dari daftar.
Hapus semua item
Kosongkan seluruh daftar.
Ganti daftar lama dengan daftar baru
Kosongkan daftar lama lalu tambahkan yang baru.
The
adapter
memiliki referensi kedata
, jadi penting bahwa saya tidak mengaturdata
untuk objek baru. Alih-alih saya membersihkan barang-barang lama daridata
dan kemudian menambahkan yang baru.Perbarui satu item
Ubah item "Domba" sehingga berbunyi "Saya suka domba."
Pindahkan satu item
Pindahkan "Domba" dari posisi
3
ke posisi1
.Kode
Ini adalah kode proyek untuk referensi Anda. Kode Adaptor RecyclerView dapat ditemukan di jawaban ini .
MainActivity.java
Catatan
notifyDataSetChanged()
, maka tidak ada animasi yang akan dilakukan. Ini juga bisa menjadi operasi yang mahal, jadi tidak disarankan untuk digunakannotifyDataSetChanged()
jika Anda hanya memperbarui satu item atau serangkaian item.Pelajaran lanjutan
sumber
Update single item
, seharusnya aku seperti kura-kuraInilah yang bekerja untuk saya:
Setelah membuat adaptor baru yang berisi daftar yang diperbarui (dalam kasus saya itu adalah database yang diubah menjadi ArrayList) dan pengaturan itu sebagai adaptor, saya mencoba
recyclerView.invalidate()
dan berfungsi.sumber
YourAdapter adapter = (YourAdapter) recyclerView.getAdapter(); adapter.yourSetterMethod(newList); adapter.notifyDataSetChanged();
Yang dikatakan, kedengarannya seperti apa yang OP coba terlebih dahulu (hanya menambahkan ini sebagai komentar sehingga dapat membantu orang lain, seperti yang berhasil dalam kasus saya).Anda memiliki 2 opsi untuk melakukan ini: menyegarkan UI dari adaptor:
atau segarkan dari recyclerView sendiri:
sumber
Pilihan lain adalah menggunakan diffutil . Ini akan membandingkan daftar asli dengan daftar baru dan menggunakan daftar baru sebagai pembaruan jika ada perubahan.
Pada dasarnya, kita dapat menggunakan DiffUtil untuk membandingkan data lama vs data baru dan membiarkannya memanggil notifyItemRangeRemoved, dan notifyItemRangeChanged dan notifyItemRangeDisertakan atas nama Anda.
Contoh cepat menggunakan diffUtet bukannya notifyDataSetChanged:
Saya melakukan pekerjaan calculDiff dari utas utama jika itu daftar besar.
sumber
getItems()
. Bagaimana Anda tahu data mana dari daftar asli yang perlu dihapus / ditambahkan / perbarui?Perbarui Data listview, gridview, dan recyclerview
atau
sumber
Cara terbaik dan paling keren untuk menambahkan data baru ke data saat ini adalah
sumber
Saya telah memecahkan masalah yang sama dengan cara yang berbeda. Saya tidak memiliki data yang saya tunggu dari latar belakang jadi mulailah dengan daftar emty.
Itu dia.
sumber
Metode ini efisien dan bagus untuk mulai menggunakan dasar
RecyclerView
.Anda dapat menerapkannya di dalam Kelas Adaptor atau dalam Fragmen atau Aktivitas Anda, tetapi dalam hal ini Anda harus instantiate Adaptor untuk memanggil metode pemberitahuan. Dalam kasus saya, saya biasanya menerapkannya di Adaptor.
sumber
Saya menemukan bahwa cara yang sangat sederhana untuk memuat ulang RecyclerView adalah dengan menelepon saja
Ini pertama-tama akan menghapus semua konten RecyclerView dan kemudian menambahkannya lagi dengan nilai yang diperbarui.
sumber
saya mendapat jawaban setelah waktu yang lama
sumber
Jika tidak ada yang disebutkan dalam komentar di atas bekerja untuk Anda. Itu mungkin berarti masalahnya ada di tempat lain.
Satu tempat saya menemukan solusinya adalah cara saya mengatur daftar ke adaptor. Dalam aktivitas saya, daftar adalah variabel instan dan saya mengubahnya secara langsung ketika ada data yang berubah. Karena itu menjadi variabel referensi ada sesuatu yang aneh terjadi. Jadi saya mengubah variabel referensi ke yang lokal dan menggunakan variabel lain untuk memperbarui data dan kemudian beralih ke
addAll()
fungsi yang disebutkan dalam jawaban di atas.sumber