Saya mencoba memperbarui item dari recycleview menggunakan notifyDataSetChanged ().
Ini adalah metode onBindViewHolder () saya di adaptor recycleview.
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
//checkbox view listener
viewHolder.getCheckbox().setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//update list items
notifyDataSetChanged();
}
});
}
Yang ingin saya lakukan adalah memperbarui daftar item, setelah saya centang kotak centang. Saya mendapatkan pengecualian ilegal:"Cannot call this method while RecyclerView is computing a layout or scrolling"
java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling
at android.support.v7.widget.RecyclerView.assertNotInLayoutOrScroll(RecyclerView.java:1462)
at android.support.v7.widget.RecyclerView$RecyclerViewDataObserver.onChanged(RecyclerView.java:2982)
at android.support.v7.widget.RecyclerView$AdapterDataObservable.notifyChanged(RecyclerView.java:7493)
at android.support.v7.widget.RecyclerView$Adapter.notifyDataSetChanged(RecyclerView.java:4338)
at com.app.myapp.screens.RecycleAdapter.onRowSelect(RecycleAdapter.java:111)
Saya juga menggunakan notifyItemChanged (), pengecualian yang sama. Adakah cara rahasia untuk memperbarui untuk memberi tahu adaptor bahwa ada sesuatu yang berubah?
android
android-recyclerview
Arthur
sumber
sumber
Jawaban:
Anda harus memindahkan metode 'setOnCheckedChangeListener ()' ke ViewHolder yang merupakan kelas dalam pada adaptor Anda.
onBindViewHolder()
bukan metode yang menginisialisasiViewHolder
. Metode ini adalah langkah menyegarkan setiap item pendaur ulang. Saat Anda meneleponnotifyDataSetChanged()
,onBindViewHolder()
akan dipanggil sebagai jumlah setiap item kali.Jadi Jika Anda
notifyDataSetChanged()
memasukkanonCheckChanged()
dan menginisialisasi kotak centangonBindViewHolder()
, Anda akan mendapatkan IllegalStateException karena panggilan metode melingkar.klik kotak centang -> onCheckedChanged () -> notifyDataSetChanged () -> onBindViewHolder () -> setel kotak centang -> onChecked ...
Sederhananya, Anda dapat memperbaiki ini dengan memasukkan satu bendera ke Adaptor.
coba ini,
sumber
AdapterViewObserver
sedangonBindViewHolder()
berlangsung.Anda bisa mereset pendengar sebelumnya sebelum membuat perubahan dan Anda tidak akan mendapatkan pengecualian ini.
sumber
Menggunakan
Handler
untuk menambahkan item dan meneleponnotify...()
dari iniHandler
memperbaiki masalah bagi saya.sumber
Saya tidak tahu, tetapi saya juga memiliki masalah yang sama. Aku memecahkan ini dengan menggunakan
onClickListner
padacheckbox
Coba ini, ini bisa membantu!
sumber
sumber
Ketika Anda memiliki Pesan Kesalahan:
Sederhana, Lakukan saja apa yang menyebabkan Pengecualian di:
sumber
Menemukan solusi sederhana -
Di sini kita membuat runnable untuk memberitahukanItemChanged untuk posisi ketika recyclerview siap menanganinya.
sumber
item CheckBox Anda sedang dalam perubahan yang dapat ditarik saat Anda menelepon
notifyDataSetChanged();
sehingga pengecualian ini akan terjadi. Coba panggilnotifyDataSetChanged();
pos Anda. Sebagai contoh:sumber
Pada awalnya saya pikir jawaban Moonsoo ( jawaban yang diterima) tidak akan berfungsi untuk saya karena saya tidak dapat menginisialisasi saya
setOnCheckedChangeListener()
di konstruktor ViewHolder karena saya harus mengikatnya setiap kali sehingga mendapat variabel posisi yang diperbarui. Tapi aku butuh waktu lama untuk menyadari apa yang dia katakan.Berikut adalah contoh dari "panggilan metode melingkar" yang ia bicarakan:
Satu-satunya masalah dengan ini, adalah bahwa ketika kita perlu menginisialisasi sakelar untuk hidup atau mati (dari keadaan tersimpan sebelumnya, misalnya), itu memanggil pendengar yang mungkin memanggil
nofityItemRangeChanged
panggilan yangonBindViewHolder
lagi. Anda tidak dapat menelepononBindViewHolder
saat Anda sudah berada dionBindViewHolder
], karena Anda tidak bisanotifyItemRangeChanged
jika Anda sudah memberitahukan bahwa kisaran item telah berubah. Tapi saya hanya perlu memperbarui UI untuk mengaktifkan atau menonaktifkannya, tidak ingin memicu apa pun.Inilah solusi yang saya pelajari dari jawaban JoniDS yang akan mencegah loop tak terbatas. Selama kita mengatur pendengar menjadi "null" sebelum kita mengatur Diperiksa, maka itu akan memperbarui UI tanpa memicu pendengar, menghindari loop tak terbatas. Lalu kita bisa mengatur pendengar setelah.
Kode JoniDS:
Solusi lengkap untuk contoh saya:
sumber
Mengapa tidak memeriksa
RecyclerView.isComputingLayout()
keadaan sebagai berikut?sumber
Sementara item sedang terikat oleh manajer tata letak, sangat mungkin bahwa Anda sedang mengatur keadaan dicentang kotak Anda, yang memicu panggilan balik.
Tentu saja ini dugaan karena Anda tidak mempublikasikan jejak tumpukan penuh.
Anda tidak dapat mengubah konten adaptor saat RV menghitung ulang tata letak. Anda dapat menghindarinya dengan tidak memanggil notifyDataSetChanged jika status item yang dicentang sama dengan nilai yang dikirim dalam panggilan balik (yang akan terjadi jika panggilan
checkbox.setChecked
memicu panggilan balik).sumber
Gunakan onClickListner pada kotak centang alih-alih OnCheckedChangeListener, Ini akan menyelesaikan masalah
sumber
Sebelum
notifyDataSetChanged()
cukup periksa dengan metode ini:recyclerView.IsComputingLayout()
sumber
Penggunaan sederhana Posting:
sumber
Saya mengalami masalah persis ini! Setelah jawaban Moonsoo tidak benar-benar mengapungkan kapalku, aku sedikit mengacau dan menemukan solusi yang berhasil untukku.
Pertama, ini beberapa kode saya:
Anda akan melihat bahwa saya secara khusus memberi tahu adaptor untuk posisi yang saya ubah, alih-alih seluruh dataset seperti yang Anda lakukan. Yang sedang berkata, meskipun saya tidak dapat menjamin ini akan bekerja untuk Anda, saya menyelesaikan masalah dengan membungkus
notifyItemChanged()
panggilan saya di blok try / catch. Ini hanya menangkap pengecualian, tetapi masih memungkinkan adaptor saya untuk mendaftarkan perubahan negara dan memperbarui tampilan!Semoga ini bisa membantu seseorang!
EDIT: Saya akui, ini mungkin bukan cara yang tepat / matang untuk menangani masalah ini, tetapi karena tampaknya tidak menyebabkan masalah dengan membiarkan pengecualian tidak ditangani, saya pikir saya akan berbagi jika itu baik cukup untuk orang lain.
sumber
Ini terjadi karena Anda mungkin mengatur 'pendengar' sebelum Anda mengkonfigurasi nilai untuk baris itu, yang membuat pendengar menjadi terpicu ketika Anda 'mengkonfigurasi nilai' untuk kotak centang.
Yang perlu Anda lakukan adalah:
sumber
sumber
cukup gunakan
isPressed()
metodeCompoundButton
dalamonCheckedChanged(CompoundButton compoundButton, boolean isChecked)
misalnya
sumber
Saya memiliki masalah yang sama menggunakan Kotak Centang dan RadioButton. Mengganti
notifyDataSetChanged()
dengannotifyItemChanged(position)
bekerja. Saya menambahkan bidang BooleanisChecked
ke model data. Kemudian saya memperbarui nilai Boolean danonCheckedChangedListener
, saya meneleponnotifyItemChanged(adapterPosition)
. Ini mungkin bukan cara terbaik, tetapi berhasil untuk saya. Nilai boolean digunakan untuk memeriksa apakah item dicentang.sumber
kebanyakan itu terjadi karena notifydatasetchang memanggil peristiwa checkbox berubah dan dalam acara itu lagi ada notifydatasetchanged .
untuk menyelesaikannya, Anda cukup memeriksa bahwa kotak centang dicentang secara terprogram atau pengguna menekannya. ada metode yang ditekan untuk itu.
jadi bungkus seluruh kode daftar di dalam metode isPressed. dan itu dilakukan.
sumber
Saya menderita masalah ini selama berjam-jam dan ini adalah bagaimana Anda dapat memperbaikinya. Tetapi sebelum Anda mulai ada beberapa syarat untuk solusi ini.
MODEL CLASS
CHECKBOX dalam ADAPTER CLASS
KONSTRUKTOR KELAS ADAPTOR & DAFTAR MODEL
ONBINDVIEW [Silakan gunakan onclick sebagai ganti onCheckChange]
}
sumber
Bagi saya masalah terjadi ketika saya keluar dari EditText oleh Done, Back, atau input luar sentuh. Hal ini menyebabkan pembaruan model dengan teks input, kemudian refresh tampilan pendaur ulang melalui pengamatan data langsung.
Masalahnya adalah bahwa kursor / fokus tetap di EditText.
Ketika saya telah menghapus fokus dengan menggunakan:
Beritahu data perubahan metode tampilan pendaur ulang tidak berhenti melempar kesalahan ini.
Saya pikir ini adalah salah satu kemungkinan alasan / solusi untuk masalah ini. Ada kemungkinan bahwa pengecualian ini dapat diperbaiki dengan cara lain karena dapat disebabkan oleh alasan yang sama sekali berbeda.
sumber