Estou usando uma implementação simples de RecyclerView
tirada do site do Android usando um StaggeredGridLayoutManager
e continuo recebendo este erro que trava meu aplicativo:
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)
Por simples, quero dizer literalmente que é a mesma implementação tirada desta página no site deles , a única diferença é que o layout do meu item de grade é um ImageView
e alguns TextView
s, então não vou me preocupar em reenviar meu código.
Alguém mais recebendo esse erro e sabe como lidar com ele?
android
android-recyclerview
StackOverflowMaster
fonte
fonte
Respostas:
Este erro é causado se em seu XML você
android:animateLayoutChanges
definir como verdadeiro e chamarnotifyDataSetChanged()
o adaptador do RecyclerView no código Java.Portanto, apenas evite usar
android:animateLayoutChanges
com RecyclerViews.fonte
RecyclerView
usaDefaultItemAnimator
por padrão.Eu tive que lidar com esse acidente também e no meu caso não teve nada a ver com isso
android:animateLayoutChanges
.O
RecyclerView
que estávamos construindo tinha mais de um tipo de vistas e algumasEditText
exibiam nelas. Depois de um tempo, identificamos que o problema estava relacionado ao foco. Esse bug acontece durante a reciclagem de seEditText
um deles está focado.Naturalmente, tentamos limpar o foco quando novos dados estavam sendo vinculados a uma visualização reciclada, mas isso não funcionou até que
android:focusableInTouchMode="true"
fosse ativadoRecycleView
. Na verdade, essa foi a única mudança necessária para que esse problema fosse embora.fonte
android:focusableInTouchMode="true"
porque isso acontece apenas às vezes em alguns dispositivos (raramente) e estou supondo que não se relaciona ao meu problema, mas rastreamento de pilha para travamento é quase o mesmo.android:focusableInTouchMode="true"
não me ajudou em nada. Então, limpei o foco noonViewDetachedFromWindow
retorno de chamada.public void onViewDetachedFromWindow(@NonNull RecyclerView.ViewHolder holder) { if (holder instanceof ItemViewHolder) { ItemViewHolder item = (ItemViewHolder) holder; if (item.editText.isFocused()) item.editText.clearFocus(); } }
Removi a
android:animateLayoutChanges
propriedade do layout e o problema foi resolvido.fonte
android:animateLayoutChanges
no meu RV também.Entre os motivos pelos quais qualquer pessoa pode enfrentar esse problema, verifique se você configurou o atributo
android:animateLayoutChanges="true"
para o RecyclerView. Isso causará falha na reciclagem e reconexão dos itens do RecyclerView. Remova-o e atribua o atributo ao contêiner pai do RecyclerView, como LinearLayout / RelativeLayout e você verá o problema desaparecer.fonte
Levei dois dias, mas não consegui contornar isso, no final, tive que desativar a pré-busca do item.
Ao configurar o gerenciador de layout, você pode simplesmente chamar
mGridLayoutManager.setItemPrefetchEnabled(false);
Isso fez com que o erro desaparecesse para mim. Espero que seja útil para alguém.
fonte
Ao usar cabeçalhos pegajosos slimfit, encontrei este erro. Foi causado por definir a primeira posição errada. Eu tenho a resposta aqui
apenas certifique-se de estar passando o valor correto para mSectionFirstPosition
fonte
item
aqui?Eu conheci esse problema esta manhã, mas não estou enfrentando o mesmo motivo mencionado acima.
Via debug descobri que a visão do item em meu ViewHolder tem
mParent
e não é nula, o que em caso normal deveria ser nenhum (é o que o log diz, "visão anexada não pode ser reciclada", eu acho que significa que se a visão filho já está ligado a um dos pais, de alguma forma causaria falha ao reciclar.)Mas eu não anexei a visualização infantil todas as vezes manualmente. E descobri que isso é feito quando tento aumentar a visualização filho em meu ViewHolder, algo como:
E o último parâmetro
attachToRoot
deve ser falso.Depois de mudar para
false
, resolvi meu problema.A propósito, só vejo que esse travamento aconteceu quando atualizo minha biblioteca de suporte para a versão mais recente 25.0.0. Antes eu estava usando a versão 23.4.0 e não vejo esse problema acontecendo. Eu acho que deve haver algo alterado na biblioteca de suporte mais recente.
Espero que esta ajuda.
fonte
Eu também encontrei o mesmo erro ao rolar no
RecyclerView
: then eu removianimateLayoutChanges="true"
no arquivo de layout paraRecyclerView
então tudo funcionou.fonte
No meu caso aconteceu porque tive uma
Transition
corrida ao tentar redimensionar o RecyclerView porque o teclado do software estava prestes a aparecer.Corrigi-lo ao excluir o RecyclerView do
Transition
usandoTransition.excludeTarget(R.id.recyclerview, true);
fonte
Há vários motivos pelos quais essa exceção é chamada. No meu caso, foi devido às animações em execução, é por isso que as visualizações ainda estão anexadas e não puderam ser removidas da visualização. Somente quando a animação for concluída, a vista poderá ser removida e reciclada.
Existem dois tipos de animação que podem afetar a reciclagem da vista de reciclagem.
1) É o
RecyclerView.ItemAnimator
- este não deve ser o problema. Isso deve ser muito seguro de usar, uma vez que verifica se há pontos de vista anexados e descartados e trata a reciclagem de maneira adequada.2)
android:animateLayoutChanges="true"
ouTransitionManager.beginDelayedTransition()
ou TransitionManager.go (), etc. - Essas animações são executadas por conta própria e controlam os itens a serem animados. Isso resulta nas vistas sendo forçadas a serem anexadas até que a animação seja concluída. O Recyclerview não tem nenhum conhecimento dessas animações, pois está fora de seu escopo. Portanto, orecyclerview
pode tentar reciclar um item pensando que ele poderia ser reciclado corretamente, mas o problema é que essas APIs ainda estão segurando as visualizações até que a animação seja concluída.Se você estiver usando
android:animateLayoutChanges="true"
ouTransitionManager.beginDelayedTransition()
ou TransitionManager.go (), etc., basta remover oRecyclerView
e seus filhos da animação.Você pode simplesmente fazer isso segurando o
Transition
e chamandoNota:
Observe que é importante
Transition.excludeChildren()
excluir todos osRecyclerview
filhos da animação e não apenas oRecyclerview
próprio.fonte
Transition.excludeChildren
. Você instancia um objeto de transição como:,val transition = AutoTransition()
chamaexcludeChildren(recyclerView, true)
esse objeto e o passa parabeginDelayedTransaction() as the second parameter
.Eu também recebia esse erro sempre que animateLayoutChanges = "true" no arquivo de layout do RecyclerView. Exclua este atributo e o erro desaparecerá!
fonte
Embora no meu caso fosse a remoção
animateOnLayoutChange
do recyclerView que corrigiu o travamento, eu ainda precisava da capacidade de animar as alterações de layout dentro do viewHolder. Para fazer isso funcionar, oLinearLayout' in the view holder needs the
animateOnLayoutChange 'to true, mas eu precisavanotifyItemChanged
para o adaptador. Isso permitiu que ambas as animações layoutTransition fossem iniciadas (para expandir e recolher o viewHolder) e também evitou a exceção descartada. Portanto, sim, evite colocar o animateOnLayoutChange no recylcerView e use os vários métodos de notificação para habilitar as animações padrão nas alterações de tamanho da visualização.fonte
Eu resolvo este problema removendo
parent.addView()
emonCreateViewHolder
Este é o meu código
Função em
android.support.v7.widget.RecyclerViewRecycler.recyclerViewHolderinternal()
verificar se meu botão já tem um pai ou não. Que se adicionarmos o botão ao pai, ele também será atribuídoRecyclerView
à suamParent
variável.fonte
Eu vi isso acontecer comigo quando usei um objeto personalizado no
ViewHolder
para oRecyclerView
adaptador.Para corrigir o problema, limpei o objeto personalizado que, no meu caso, era um temporizador no
onViewRecycled(ViewHolder holder)
adaptador, conforme abaixo:Isso corrigiu o bug.
fonte
fonte
1 、
remove
: remove os dados da lista.2 、
notifyDataSetChanged
: notificationDataSetChanged ();3 、
notifyItemRemoved
: mostra animação.4 、
notifyItemRangeChanged
: tamanho da visão do intervalo e redesenhar oviewHolders(onBindViewHolder methods)
fonte
notifyItemRemoved
ao removerfooter
e travar o aplicativo, altere paranotifyDataSetChanged
e agora ele funciona bem. obrigadoNo meu caso, usei o
TransitionManager.beginDelayedTransition()
antes de adicionar uma visualização no topo do recyclerView. Tirei oTransitionManager.beginDelayedTransition()
e sem travar.fonte
Resolvi esse problema ligando para
no construtor do adaptador e substituindo
getItemId
no adaptador:fonte
Remover
android:animateLayoutChanges="true"
de reciclar ou definirandroid:animateLayoutChanges="false"
fonte
eu uso
com.squareup.picasso.RequestCreator
para redimensionar dinamicamente o tamanho do ImageView após baixar a imagem da Internet e salvar a largura e a altura redimensionadas para preservar o tamanho da visualização. Recebi essa exceção porque salvei
LayoutParams
em umMap
, e em meu onBindViewHolder, recuperei e defini diretamente como meuImageView
. Eu corrijo isso usandoImmutablePair<Integer, Integer>
apenas o tamanho de ImageView, em vez de muitos outros estados, e uso o código a seguir para restaurá-lo.fonte
Para mim, o mesmo bug é causado por um LayoutTransition em um ViewGroup de nível superior.
fonte
Deixe-me adicionar outra solução possível para esse tipo de problema, por favor. Eu tive o mesmo problema com a biblioteca superSlim para cabeçalhos pegajosos em
RecyclerView
. Eu costumavaMatrixCursor
definir os dados paraRecyclerViewCursorAdapter
. O motivo desse problema era que as colunas de ID são iguais a0
para todos os cabeçalhos. Espero que isso ajude alguém a economizar alguns dias de depuração.fonte
No meu caso, o problema era devido à implementação incorreta desse método
public long getItemId(int position)
(substituído doRecyclerView.Adapter
método).O código antigo obterá dois ids diferentes para o mesmo item (no meu caso é o item de rodapé), depois de consertar a implementação, o problema desapareceu.
fonte
Solução alternativa se o motivo da Exceção for o que itemView tem pai. No código, onde você notificouItemRemoved (posição), remova itemView de RecyclerView:
fonte
Um caso peculiar que ocorreu para mim foi que eu tinha um membro de visualização no adaptador e estava preguiçoso instanciando uma visualização que não há necessidade de fazer com a visualização de reciclagem.
Também vai contra os princípios de reciclar visualizações, que são o armazenamento de uma referência para a visualização neste caso. Dou um exemplo rápido abaixo:
fonte
esta exceção não é causa de
ou
esta resposta correta final é apenas porque você definiu um LayoutParams WRONG .
o nameLP está OK. o nameLP2 ocorre o crash .bug está aqui.
Eu tento todas as respostas desta página. Confie em mim.
fonte
Eu tive esse problema porque eu substituir
equals()
ehashcode()
método deViewHolder
deRecyclerView
.ViewHolder calculando a igualdade de dados e hashcode, então a lógica de reciclagem não funcionou e caiu, eu só remover a sobrescrever e fixa.fonte