Saya menggunakan implementasi sederhana yang RecyclerView
diambil dari situs web Android menggunakan a StaggeredGridLayoutManager
dan saya terus mendapatkan kesalahan ini yang membuat aplikasi saya mogok:
java.lang.IllegalArgumentException: Scrapped or attached views may not be recycled. isScrap:false isAttached:true
at android.support.v7.widget.RecyclerView$Recycler.recycleViewHolderInternal(RecyclerView.java:3501)
at android.support.v7.widget.RecyclerView$LayoutManager.scrapOrRecycleView(RecyclerView.java:5355)
at android.support.v7.widget.RecyclerView$LayoutManager.detachAndScrapAttachedViews(RecyclerView.java:5340)
at android.support.v7.widget.StaggeredGridLayoutManager.onLayoutChildren(StaggeredGridLayoutManager.java:572)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:1918)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2155)
at android.view.View.layout(View.java:14008)
at android.view.ViewGroup.layout(ViewGroup.java:4373)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1021)
at android.view.View.layout(View.java:14008)
at android.view.ViewGroup.layout(ViewGroup.java:4373)
at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
at android.view.View.layout(View.java:14008)
at android.view.ViewGroup.layout(ViewGroup.java:4373)
at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
at android.view.View.layout(View.java:14008)
at android.view.ViewGroup.layout(ViewGroup.java:4373)
at android.support.v7.internal.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:502)
at android.view.View.layout(View.java:14008)
at android.view.ViewGroup.layout(ViewGroup.java:4373)
at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
at android.view.View.layout(View.java:14008)
at android.view.ViewGroup.layout(ViewGroup.java:4373)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1663)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1521)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
at android.view.View.layout(View.java:14008)
at android.view.ViewGroup.layout(ViewGroup.java:4373)
at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
at android.view.View.layout(View.java:14008)
at android.view.ViewGroup.layout(ViewGroup.java:4373)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1892)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1711)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:989)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4351)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
at android.view.Choreographer.doCallbacks(Choreographer.java:562)
at android.view.Choreographer.doFrame(Choreographer.java:532)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
Sederhananya, maksud saya itu adalah implementasi yang sama yang diambil dari halaman ini di situs web mereka , satu-satunya perbedaan adalah bahwa tata letak item grid saya adalah ImageView
dan beberapa TextView
, jadi saya tidak akan repot-repot memposting ulang kode saya.
Adakah orang lain yang mendapatkan kesalahan ini dan tahu cara mengatasinya?
android
android-recyclerview
StackOverflowMaster
sumber
sumber
Jawaban:
Kesalahan ini terjadi jika dalam XML Anda telah
android:animateLayoutChanges
disetel ke true dan Anda memanggilnotifyDataSetChanged()
adaptor RecyclerView dalam kode Java.Jadi, hindari saja penggunaan
android:animateLayoutChanges
dengan RecyclerViews.sumber
RecyclerView
digunakanDefaultItemAnimator
secara default.Saya harus berurusan dengan kecelakaan ini juga dan dalam kasus saya itu tidak ada hubungannya dengan
android:animateLayoutChanges
.Bangunan yang
RecyclerView
kami bangun memiliki lebih dari satu jenis pemandangan di dalamnya dan beberapa adaEditText
di dalamnya. Setelah beberapa saat kami menyematkan masalah menjadi fokus terkait. Bug ini terjadi saat daur ulangEditText
dan salah satunya difokuskan.Secara alami kami mencoba membersihkan fokus saat data baru sedang terikat ke tampilan daur ulang, tetapi itu tidak berfungsi hingga
android:focusableInTouchMode="true"
diaktifkanRecycleView
. Sebenarnya hanya itu perubahan yang diperlukan pada akhirnya agar masalah ini bisa hilang.sumber
android:focusableInTouchMode="true"
karena itu hanya terjadi kadang-kadang di beberapa perangkat (jarang) dan saya kira itu tidak berhubungan dengan masalah saya tetapi jejak tumpukan untuk crash hampir sama.android:focusableInTouchMode="true"
tidak membantu saya sama sekali. Jadi saya membersihkan fokus dalamonViewDetachedFromWindow
panggilan balik.public void onViewDetachedFromWindow(@NonNull RecyclerView.ViewHolder holder) { if (holder instanceof ItemViewHolder) { ItemViewHolder item = (ItemViewHolder) holder; if (item.editText.isFocused()) item.editText.clearFocus(); } }
Saya menghapus
android:animateLayoutChanges
dari properti tata letak dan masalah telah diselesaikan.sumber
android:animateLayoutChanges
di RV saya juga.Di antara alasan siapa pun dapat menghadapi masalah ini, periksa apakah Anda telah menyetel atribut
android:animateLayoutChanges="true"
ke RecyclerView. Ini akan menyebabkan daur ulang dan pemasangan kembali item RecyclerView gagal. Hapus dan tetapkan atribut ke container induk RecyclerView, seperti LinearLayout / RelativeLayout dan Anda akan melihat masalahnya hilang.sumber
Saya butuh waktu dua hari tetapi tidak bisa menyiasatinya, pada akhirnya, saya harus menonaktifkan prefetch item.
Saat mengatur manajer tata letak, Anda cukup memanggil
mGridLayoutManager.setItemPrefetchEnabled(false);
Itu membuat kesalahan pergi untuk saya. Semoga bermanfaat bagi seseorang.
sumber
Saat menggunakan header lengket slimfit, saya mengalami kesalahan ini. Hal itu disebabkan karena salah setting posisi pertama. Saya mendapat jawabannya di sini
cukup pastikan Anda memberikan nilai yang benar untuk mSectionFirstPosition
sumber
item
disini?Saya menemui masalah ini pagi ini, tetapi saya tidak menghadapi alasan yang sama seperti yang disebutkan di atas.
Melalui debug saya menemukan bahwa tampilan item di ViewHolder saya memiliki
mParent
dan itu bukan null, yang dalam kasus normal seharusnya tidak ada (itulah yang dikatakan log, "tampilan terlampir tidak dapat didaur ulang", saya pikir itu berarti jika tampilan anak sudah terpasang ke induk, itu akan menyebabkan kegagalan saat mendaur ulang.)Tapi saya tidak melampirkan tampilan anak setiap kali secara manual. Dan saya menemukan bahwa itu selesai ketika saya mencoba untuk memekarkan tampilan anak di ViewHolder saya, seperti:
Dan parameter terakhir
attachToRoot
harus salah.Setelah saya mengubahnya menjadi
false
, saya memperbaiki masalah saya.Omong-omong, saya hanya melihat kerusakan ini terjadi saat saya meningkatkan pustaka dukungan saya ke versi terbaru 25.0.0. Sebelumnya saya menggunakan versi 23.4.0 dan saya tidak melihat masalah ini terjadi. Saya kira harus ada sesuatu yang berubah di pustaka dukungan terbaru.
Semoga bantuan ini.
sumber
Saya juga mengalami kesalahan yang sama saat menggulir di
RecyclerView
: lalu saya menghapusanimateLayoutChanges="true"
file tata letak agarRecyclerView
semuanya berfungsi.sumber
Dalam kasus saya, itu terjadi karena saya
Transition
menjalankan ketika mencoba mengubah ukuran RecyclerView karena keyboard perangkat lunak akan ditampilkan.Saya memperbaikinya dengan mengecualikan RecyclerView dari
Transition
dengan menggunakanTransition.excludeTarget(R.id.recyclerview, true);
sumber
Ada sejumlah alasan mengapa pengecualian ini disebut. Dalam kasus saya, itu karena animasi yang berjalan, itulah mengapa tampilan masih terpasang dan tidak dapat dihapus ke tampilan. Hanya setelah animasi selesai maka tampilan dapat dihapus dan didaur ulang.
Ada dua jenis animasi yang dapat memengaruhi daur ulang recyclerview.
1) Apakah
RecyclerView.ItemAnimator
- ini seharusnya tidak menjadi masalah. Ini seharusnya cukup aman untuk digunakan karena memeriksa tampilan yang dilampirkan dan dihapus serta menangani daur ulang dengan benar.2)
android:animateLayoutChanges="true"
atauTransitionManager.beginDelayedTransition()
atau TransitionManager.go (), dll. - Animasi ini berjalan sendiri dan memegang item yang akan dianimasikan. Hasil ini memaksa tampilan untuk dilampirkan sampai animasi selesai. Recyclerview tidak memiliki pengetahuan tentang animasi ini karena berada di luar cakupannya. Oleh karena itu,recyclerview
mungkin mencoba untuk mendaur ulang item yang berpikir itu dapat didaur ulang dengan benar tetapi masalahnya adalah bahwa API ini masih memegang tampilan sampai animasi selesai.Jika Anda menggunakan
android:animateLayoutChanges="true"
atauTransitionManager.beginDelayedTransition()
atau TransitionManager.go (), dll. Cukup hapusRecyclerView
dan turunannya dari animasi.Anda cukup melakukan ini dengan memegang
Transition
dan memanggilcatatan:
Perhatikan bahwa penting untuk menggunakan
Transition.excludeChildren()
mengecualikan semuaRecyclerview
anak dari animasi dan bukan hanyaRecyclerview
dirinya sendiri.sumber
Transition.excludeChildren
. Anda membuat instance objek transisi seperti:,val transition = AutoTransition()
panggilexcludeChildren(recyclerView, true)
objek ini dan teruskan kebeginDelayedTransaction() as the second parameter
.Saya juga mendapatkan kesalahan ini setiap kali saya memiliki animateLayoutChanges = "true" dalam file layout untuk RecyclerView. Hapus atribut ini dan kesalahan akan hilang!
sumber
Sementara dalam kasus saya itu menghapus
animateOnLayoutChange
dari recyclerView yang memperbaiki crash, saya masih membutuhkan kemampuan untuk menganimasikan perubahan tata letak dalam viewHolder. Agar ini bekerja,LinearLayout' in the view holder needs the
animateOnLayoutChange 'menjadi true, tetapi saya perlu kenotifyItemChanged
adaptor. Ini kemudian memungkinkan kedua animasi layoutTransition untuk dimulai (untuk meluaskan dan menciutkan viewHolder), dan juga menghindari pengecualian yang dihapus. Jadi ya, hindari meletakkan animateOnLayoutChange di recylcerView dan gunakan berbagai metode notify untuk mengaktifkan animasi default pada perubahan ukuran tampilan.sumber
Aku memecahkan masalah ini dengan menghapus
parent.addView()
dionCreateViewHolder
Ini kode saya
Berfungsi di
android.support.v7.widget.RecyclerViewRecycler.recyclerViewHolderinternal()
cek apakah tombol saya sudah menjadi orang tua atau belum. Yang mana jika kita menambahkan tombol ke induk, itu juga akan ditetapkanRecyclerView
kemParent
variabelnya.sumber
Saya melihat ini terjadi pada saya ketika saya menggunakan objek khusus di
ViewHolder
untukRecyclerView
adaptor.Untuk memperbaiki masalah ini saya membersihkan objek khusus yang dalam kasus saya adalah pengatur waktu
onViewRecycled(ViewHolder holder)
untuk adaptor seperti di bawah ini:Ini memperbaiki bug.
sumber
sumber
1 、
remove
: hapus data dari daftar.2 、
notifyDataSetChanged
: notifyDataSetChanged ();3 、
notifyItemRemoved
: tampilkan animasi.4 、
notifyItemRangeChanged
: rentang ukuran tampilan dan gambar ulangviewHolders(onBindViewHolder methods)
sumber
notifyItemRemoved
saat menghapusfooter
dan aplikasi macet, ubah kenotifyDataSetChanged
dan sekarang berfungsi dengan baik. terima kasihDalam kasus saya, saya menggunakan
TransitionManager.beginDelayedTransition()
sebelum menambahkan tampilan di atas recyclerView. Saya menghapusTransitionManager.beginDelayedTransition()
dan tidak ada crash.sumber
Saya memecahkan masalah ini dengan menelepon
di konstruktor adaptor dan menimpa
getItemId
di adaptor:sumber
Hapus
android:animateLayoutChanges="true"
dari recycleview atau setandroid:animateLayoutChanges="false"
sumber
saya menggunakan
com.squareup.picasso.RequestCreator
untuk mengubah ukuran ImageView secara dinamis setelah mendownload gambar dari Internet, dan menyimpan lebar dan tinggi yang diubah ukurannya untuk mempertahankan ukuran tampilan. Saya mendapatkan Pengecualian ini karena saya menyimpannya
LayoutParams
diMap
, dan di onBindViewHolder, saya mengambilnya dan langsung mengaturnya ke milik sayaImageView
. Saya memperbaikinya dengan menggunakanImmutablePair<Integer, Integer>
hanya untuk menyimpan ukuran ImageView daripada banyak negara lain, dan menggunakan kode berikut untuk memulihkannya.sumber
Bagi saya, bug yang sama disebabkan oleh LayoutTransition pada ViewGroup level yang lebih tinggi.
sumber
Izinkan saya menambahkan kemungkinan perbaikan lain untuk masalah semacam ini. Saya memiliki masalah yang sama dengan pustaka superSlim untuk header tempel
RecyclerView
. Saya biasaMatrixCursor
mengatur data keRecyclerViewCursorAdapter
. Alasan untuk masalah ini adalah kolom ID sama dengan0
untuk semua tajuk. Harapan itu akan membantu seseorang untuk menghemat beberapa hari debugging.sumber
Dalam kasus saya, masalahnya adalah karena penerapan metode ini salah
public long getItemId(int position)
(diganti dariRecyclerView.Adapter
metode).Kode lama akan mendapatkan dua id berbeda untuk item yang sama (dalam kasus saya ini adalah item footer), setelah memperbaiki implementasi, masalah telah hilang.
sumber
Solusi solusi jika alasan Exception adalah itemView memiliki induk. Dalam kode, di mana Anda memiliki notifyItemRemoved (position), hapus itemView dari RecyclerView:
sumber
Kasus aneh yang terjadi pada saya adalah bahwa saya memiliki anggota tampilan di adaptor dan saya malas memberi contoh tampilan yang tidak perlu dilakukan dengan tampilan daur ulang.
Ini juga bertentangan dengan prinsip tampilan daur ulang yang sebagai referensi Anda untuk menyimpan tampilan dalam kasus ini. Saya berikan contoh singkat di bawah ini:
sumber
pengecualian ini bukan penyebab
atau
jawaban terakhir yang benar ini hanya karena Anda menetapkan LayoutParams yang SALAH .
nameLP-nya OK. nameLP2 terjadi crash. bug di sini.
Saya mencoba semua jawaban dari halaman ini. percayalah kepadaku.
sumber
Saya memiliki masalah ini karena saya menimpa
equals()
danhashcode()
metodeViewHolder
dariRecyclerView
.ViewHolder dengan menghitung kesetaraan data dan kode hash, maka logika recycle tidak bekerja dan jatuh, saya hanya menghapus menimpa dan tetap.sumber