您的位置:首页 > 移动开发

java.lang.IllegalArgumentException: Scrapped or attached views may not be recycled. isScrap:false is

2016-11-08 16:19 573 查看


在尝试使用LayoutTransition自定义RecyclerView的添加或者移除item的动画时,出现了此Bug.在stackoverflow找到了解决方案,在此记录备案。

先还原下问题, RecyclerView在XML中是这么定义的

<android.support.v7.widget.RecyclerView
android:id="@+id/rv_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">

</android.support.v7.widget.RecyclerView>


先看stackoverflow中的解决方案,在答案中说到,造成错误的原因是将android:animateLayoutChanges设置为true,并且应该避免android:animateLayoutChanges属性和RecyclerView一起使用。



采用此种方案确实解决了问题,但是确实有点理解,于是翻看了官方文档,来确认下:

从RecyclerView源码中可以清晰的看到,其默认使用了DefaultItemAnimator。跟踪DefaultItemAnimator的父接口,最后发现,其最终继承于RecyclerView.ItemAnimator,该类是专门为RecyclerView的数据变化而封装的一个抽象类。



官方文档对Scrap (view)有这么一段介绍,从中可以清晰的看出,废弃的子视图与父RecyclerView完全分离,可以重复利用的,如果不需要重新绑定,则可以未修改。如果修改子视图,应该在数据显示以前,由适配器重建一个子视图。

Scrap (view): A child view that has entered into a temporarily detached state during layout. Scrap views may be reused without becoming fully detached from the parent RecyclerView, either unmodified if no rebinding is required or modified by the adapter if the view was considered dirty.
Dirty (view): A child view that must be rebound by the adapter before being displayed.


如果想自定义Item动画,需调用setItemAnimator(RecyclerView.ItemAnimator animator)方法,其参数为RecyclerView.ItemAnimator,而其本身与LayoutTransition就没有联系,也就是说从一开始想法就错了。

接着再看看官方文档对于LayoutTransition的介绍,可以清晰的看到LayoutTransition的动画效果,只有当ViewGroup中有View添加、删除、隐藏、显示的时候才会体现出来。



从另一方面来说,RecyclerView是对数据的显示,并未增加或减少控件。在RecyclerView的适配数据发生改变时,其Adapter回重建子视图,鉴于RecyclerView的内部缓存,子视图会重复利用,但并不是真正意义的增加或删除控件,即使不冲突,我想应该也不会出现动画效果。如果想实现RecyclerView的Item的动画效果,应该采用LayoutAnimation,一开始方向就错了,所以Bug也就出现了。

参考资料:

1. https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html

2. http://stackoverflow.com/questions/26477660/recyclerview-crashes-when-scrapped-or-attached-views-may-not-be-recycled
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐