Я использую простую реализацию, RecyclerView
взятую с веб-сайта Android, с помощью, StaggeredGridLayoutManager
и я продолжаю получать эту ошибку, которая приводит к сбою моего приложения:
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)
Проще говоря, я буквально имею в виду ту же реализацию, что и на этой странице на их веб-сайте , с той лишь разницей, что макет моего элемента сетки - это ImageView
и пара TextView
s, поэтому я не буду утруждать себя репостом своего кода.
Кто-нибудь еще получает эту ошибку и знает, как с ней бороться?
android
android-recyclerview
StackOverflowMaster
источник
источник
Ответы:
Эта ошибка возникает, если в вашем XML вы
android:animateLayoutChanges
установили значение true и вызываетеnotifyDataSetChanged()
адаптер RecyclerView в коде Java.Поэтому просто избегайте использования
android:animateLayoutChanges
с RecyclerViews.источник
RecyclerView
используетDefaultItemAnimator
по умолчанию.Мне тоже приходилось иметь дело с этой аварией, и в моем случае это не имело никакого отношения
android:animateLayoutChanges
.В том, что
RecyclerView
мы строили, было больше одного вида видов, и некоторые из них былиEditText
в них. Через некоторое время мы решили, что проблема связана с фокусом. Эта ошибка возникает при переработкеEditText
s, и одна из них сфокусирована.Естественно, мы пытались очистить фокус, когда новые данные привязываются к переработанному представлению, но это не сработало, пока
android:focusableInTouchMode="true"
не было включеноRecycleView
. Фактически, это единственное изменение, которое потребовалось, чтобы эта проблема исчезла.источник
android:focusableInTouchMode="true"
потому что это случается только иногда на некоторых устройствах (редко), и я предполагаю, что это не связано с моей проблемой, но трассировка стека для сбоя почти такая же.android:focusableInTouchMode="true"
мне совершенно не помогла. Поэтому я снял фокус сonViewDetachedFromWindow
обратного вызова.public void onViewDetachedFromWindow(@NonNull RecyclerView.ViewHolder holder) { if (holder instanceof ItemViewHolder) { ItemViewHolder item = (ItemViewHolder) holder; if (item.editText.isFocused()) item.editText.clearFocus(); } }
Я удалил
android:animateLayoutChanges
свойство из макета, и проблема была решена.источник
android:animateLayoutChanges
на свой автофургон.Среди причин, по которым кто-либо может столкнуться с этой проблемой, проверьте, установили ли вы атрибут
android:animateLayoutChanges="true"
RecyclerView. Это приведет к сбою повторного использования и повторного подключения элементов RecyclerView. Удалите его и назначьте атрибут родительскому контейнеру RecyclerView, например LinearLayout / RelativeLayout, и вы увидите, что проблема исчезла.источник
Это заняло у меня два дня, но я не мог обойти это, в конце концов, мне пришлось отключить предварительную выборку элементов.
При настройке менеджера компоновки вы можете просто вызвать
mGridLayoutManager.setItemPrefetchEnabled(false);
Это заставило меня устранить ошибку. Надеюсь, это будет кому-то полезно.
источник
Я также столкнулся с той же ошибкой при прокрутке
RecyclerView
: затем я удалилanimateLayoutChanges="true"
файл макета, чтобыRecyclerView
все работало.источник
При использовании липких заголовков slimfit я столкнулся с этой ошибкой. Это было вызвано неправильной установкой первой позиции. Я получил ответ здесь
просто убедитесь, что вы передаете правильное значение для mSectionFirstPosition
источник
item
здесь?Я столкнулся с этой проблемой сегодня утром, но не сталкиваюсь с той же причиной, о которой говорилось выше.
С помощью отладки я обнаружил, что представление элемента в моем ViewHolder имеет
mParent
значения NULL, что в нормальном случае не должно быть пустым (в журнале говорится, что «прикрепленное представление не может быть переработано», я думаю, это означает, что если дочернее представление уже прикреплен к родительскому элементу, это каким-то образом может вызвать сбой при переработке.)Но я не каждый раз прикреплял дочерний вид вручную. И я обнаружил, что это происходит, когда я пытаюсь раздуть дочернее представление в моем ViewHolder, что-то вроде:
И последний параметр
attachToRoot
должен быть ложным.После того, как я изменил его на
false
, я решил свою проблему.Кстати, я вижу, что этот сбой произошел только тогда, когда я обновляю свою библиотеку поддержки до последней версии 25.0.0. Раньше я использовал версию 23.4.0 и не видел, чтобы эта проблема возникала. Думаю, в последней библиотеке поддержки нужно что-то изменить.
Надеюсь на эту помощь.
источник
В моем случае это произошло из-за того, что у меня была
Transition
ошибка при попытке изменить размер RecyclerView, потому что программная клавиатура собиралась показать.Я исправил это, исключив RecyclerView из
Transition
с помощьюTransition.excludeTarget(R.id.recyclerview, true);
источник
Это исключение вызывается по ряду причин. В моем случае это произошло из-за запущенной анимации, поэтому представления все еще прикреплены и не могут быть удалены из представления. Только когда анимация будет завершена, вид можно будет удалить и переработать.
Есть два типа анимации, которые могут повлиять на переработку recyclerview.
1) Том
RecyclerView.ItemAnimator
- это не должно быть проблемой. Это должно быть в значительной степени безопасным в использовании, поскольку оно проверяет наличие прикрепленных и удаленных видов и правильно обрабатывает переработку.2)
android:animateLayoutChanges="true"
илиTransitionManager.beginDelayedTransition()
или TransitionManager.go () и т. Д. - Эти анимации запускаются сами по себе и захватывают элементы для анимации. Это приводит к принудительному прикреплению представлений до завершения анимации. Reclerview ничего не знает об этих анимациях, так как это выходит за рамки его возможностей. Поэтому ониrecyclerview
могут попытаться переработать элемент, полагая, что он может быть переработан должным образом, но проблема в том, что эти API-интерфейсы все еще удерживают представления, пока анимация не завершится.Если вы используете
android:animateLayoutChanges="true"
orTransitionManager.beginDelayedTransition()
или TransitionManager.go () и т. Д., Просто удалитеRecyclerView
и его дочерние элементы из анимации.Вы можете просто сделать это, взяв
Transition
и позвонивПримечание:
Обратите внимание, что важно использовать
Transition.excludeChildren()
для исключения всехRecyclerview
дочерних элементов из анимации, а не только ееRecyclerview
самого.источник
Transition.excludeChildren
. Вы создаете экземпляр объекта перехода, например:,val transition = AutoTransition()
вызываетеexcludeChildren(recyclerView, true)
этот объект и передаете егоbeginDelayedTransaction() as the second parameter
.Я тоже получал эту ошибку всякий раз, когда у меня был animateLayoutChanges = "true" в файле макета для RecyclerView. Удалите этот атрибут и ошибка исчезнет!
источник
Хотя в моем случае он удалялся
animateOnLayoutChange
из recyclerView, который исправил сбой, мне по-прежнему нужна была возможность анимировать изменения макета в viewHolder. Чтобы это работало, дляLinearLayout' in the view holder needs the
animateOnLayoutChange 'значение true, но мне нужно былоnotifyItemChanged
для адаптера. Это затем позволило запустить обе анимации layoutTransition (для расширения и свертывания viewHolder), а также позволило избежать исключения исключения. Итак, да, не помещайте animateOnLayoutChange в recylcerView и используйте различные методы уведомления, чтобы включить анимацию по умолчанию при изменении размера представления.источник
Решаю эту проблему, удалив
parent.addView()
вonCreateViewHolder
Это мой код
Функция
android.support.v7.widget.RecyclerViewRecycler.recyclerViewHolderinternal()
проверки, есть ли у моей кнопки родительский элемент или нет. Что, если мы добавим кнопку к родительскому элементу, она также будет назначенаRecyclerView
егоmParent
переменной.источник
Я видел, как это произошло со мной, когда я использовал настраиваемый объект
ViewHolder
дляRecyclerView
адаптера.Чтобы решить эту проблему, я очистил настраиваемый объект, который в моем случае был таймером
onViewRecycled(ViewHolder holder)
для адаптера, как показано ниже:Это исправило ошибку.
источник
источник
1 、
remove
: удалить данные из списка.2 、
notifyDataSetChanged
: notifyDataSetChanged ();3 、
notifyItemRemoved
: показать анимацию.4 、
notifyItemRangeChanged
: размер просмотра диапазона и перерисоватьviewHolders(onBindViewHolder methods)
источник
notifyItemRemoved
при удаленииfooter
и сбое приложения, измените его на,notifyDataSetChanged
и теперь он работает нормально. спасибоВ моем случае я использовал
TransitionManager.beginDelayedTransition()
перед добавлением представления поверх recyclerView. Я удалилTransitionManager.beginDelayedTransition()
и никаких сбоев.источник
Я решил эту проблему, позвонив
в конструкторе адаптера и переопределение
getItemId
в адаптере:источник
Удалить
android:animateLayoutChanges="true"
из корзины или установитьandroid:animateLayoutChanges="false"
источник
я использую
com.squareup.picasso.RequestCreator
для динамического изменения размера ImageView после загрузки изображения из Интернета и сохраняет измененные ширину и высоту, чтобы сохранить размер представления. Я получил это исключение, потому что я сохранил
LayoutParams
егоMap
, а в моем onBindViewHolder я извлек его и напрямую установил в свойImageView
. Я исправляю это,ImmutablePair<Integer, Integer>
сохраняя только размер ImageView, а не множество других состояний, и использую следующий код для его восстановления.источник
Для меня такая же ошибка, вызванная LayoutTransition на более высоком уровне ViewGroup.
источник
Позвольте мне добавить еще одно возможное решение этой проблемы, пожалуйста. У меня была такая же проблема с библиотекой superSlim для липких заголовков
RecyclerView
. Раньше яMatrixCursor
устанавливал данные вRecyclerViewCursorAdapter
. Причина этой проблемы заключалась в том, что столбцы идентификаторов равны0
для всех заголовков. Надеюсь, что это поможет кому-то сэкономить пару дней на отладке.источник
В моем случае проблема была из-за неправильной реализации этого метода
public long getItemId(int position)
(переопределено изRecyclerView.Adapter
метода).Старый код получит два разных идентификатора для одного и того же элемента (в моем случае это элемент нижнего колонтитула), после исправления реализации проблема исчезла.
источник
Обходное решение, если причиной исключения является родительский элемент itemView. В коде, где у вас есть notifyItemRemoved (position), удалите itemView из RecyclerView:
источник
Своеобразный случай, который произошел для меня, заключался в том, что у меня был элемент представления в адаптере, и я был ленив при создании экземпляра представления, которого нет необходимости делать с представлением корзины.
Это также противоречит принципам повторного использования представлений, которые в данном случае сохраняют ссылку на представление. Ниже я привожу краткий пример:
источник
это исключение не является причиной
или
этот окончательный правильный ответ просто потому, что вы установили НЕПРАВИЛЬНЫЙ LayoutParams .
имяLP в порядке. имяLP2 происходит сбой. ошибка здесь.
Пробую все ответы на этой странице. Доверьтесь мне.
источник
Я имел этот вопрос , потому что я перезаписать
equals()
иhashcode()
методViewHolder
изRecyclerView
.ViewHolder путем вычисления равенства данных и хэш - код, то логика рецикл не сделал работу и разбился, я просто удалить перезапись и фиксировано.источник