自支持库 25.0.0 起,已删除或附加的视图可能无法回收利用。

7

有时候,当我快速滚动列表时,所有的recyclerview都会崩溃,自从我更新到支持lib 25.0.0版本以来。没有布局动画,使用支持库小于25时一切正常。

异常是在RecyclerView中抛出的,因为holder.itemView.getparent()不为空。

    if (holder.isScrap() || holder.itemView.getParent() != null) {
            throw new IllegalArgumentException(
                    "Scrapped or attached views may not be recycled. isScrap:"
                            + holder.isScrap() + " isAttached:"
                            + (holder.itemView.getParent() != null));
        }

有人经历过这种行为吗?

如果您提供一个演示问题的最小完整可复现示例(MCVE),以及崩溃的完整堆栈跟踪,您可能会有更好的运气。 - CommonsWare
这里也遇到了同样的问题,并且只发生在我升级了支持库到25.0.0版本之后。有人在这里创建了一个问题: https://code.google.com/p/android/issues/detail?id=226353&can=1&q=reportedby%3DDeveloper%20-has%3Atriaged%20-has%3Apriority%20component%3DSupport-Libraries%20-has%3Ablocked&colspec=ID%20Status%20Priority%20Owner%20Summary%20Stars%20Reporter%20Opened&start=1400 但看起来谷歌支持库团队关闭了它,因为缺少复现步骤。 - Anthonyeef
1
顺便说一下,我只在GridLayoutManager下遇到了这个问题。当我使用LinearLayoutManager时,一切看起来都很好。 - Anthonyeef
2个回答

11
为了避免此问题导致崩溃,您需要从您的适配器中调用setHasStableIds(boolean)方法,并将参数设置为true。
adapter.setHasStableIds(true);

解释: 在调用adapter.notifyDataSetChanged();时出现问题。

recyclerView随后调用detachAndScrapAttachedViews(recycler);。它会暂时分离并回收所有当前附加的子视图。视图将被回收到给定的Recycler中。Recycler可能会优先重用回收视图。

然后调用scrapOrRecycleView(recycler, (int) position, (View) child);。此函数检查“hasStableIds”是true还是false。如果为false,则会出现以下错误:

"Scrapped or attached views may not be recycled."

稳定的ID允许ViewRecyclerViewListView等)在notifyDataSetChanged调用之间项目保持不变时进行优化。 hasStableIds() == true表示项ID在基础数据更改时保持稳定。

如果项目ID是稳定的,则可以通过视图进行重用,即“回收”,使得在调用notifyDataSetChanged()后重新渲染的过程高效。如果项目ID不稳定,则不能保证已回收该项,因为无法跟踪它们。

注意:将setHasStableIds()设置为true不是请求稳定ID的方法,而是告诉Recycler/List/Grid Views您正在提供所述的稳定性。


请帮我解答这个问题:https://dev59.com/6J3ha4cB1Zd3GeqPZsqi - Reprator

-1

如果在XML中设置RecyclerViewandroid:orientation="horizontal",也可能会发生这种情况。删除它将防止崩溃。


任何想要踩这个的人,请将该行添加到您的“RecyclerView”中并检查是否会导致崩溃。 - Ali Kazi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接