问题描述
Fabric上报的bug,一开始的时候不知道问题出在哪里,然后每个用到RecyclerView的地方都排查了一下终于找到了复现的步骤。
有一个列表支持左右滑动删除,Item的布局里面也有删除按钮,点击之后有删除的动画,然后在动画结束的监听里面调用了adapter.notifyItemRemoved()方法。复现步骤是:在执行删除Item动画的时候立即上下滑动RecyclerView,必崩。
Fabric上详细错误信息如下:
[C++] 纯文本查看 复制代码 Fatal Exception: java.lang.IllegalArgumentException: Called attach on a child which is not detached: ViewHolder{4244ca70 position=0 id=-1, oldPos=-1, pLpos:-1 not recyclable(1)}
at android.support.v7.widget.RecyclerView$5.attachViewToParent(RecyclerView.java:719)
at android.support.v7.widget.ChildHelper.attachViewToParent(ChildHelper.java:239)
at android.support.v7.widget.RecyclerView.addAnimatingView(RecyclerView.java:1222)
at android.support.v7.widget.RecyclerView.animateDisappearance(RecyclerView.java:3594)
at android.support.v7.widget.RecyclerView$4.processDisappeared(RecyclerView.java:485)
at android.support.v7.widget.ViewInfoStore.process(ViewInfoStore.java:244)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep3(RecyclerView.java:3444)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3194)
at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1593)
at android.support.v7.widget.RecyclerView$1.run(RecyclerView.java:323)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:788)
at android.view.Choreographer.doCallbacks(Choreographer.java:591)
at android.view.Choreographer.doFrame(Choreographer.java:559)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:774)
at android.os.Handler.handleCallback(Handler.java:808)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
at dalvik.system.NativeStart.main(NativeStart.java)
可能的原因
根据Google Issue Tracker #37045161 上面的解释,当Item发生改变的时候,改变的动画会创建两份ViewHolder,旧的ViewHolder 淡出,新的ViewHolder 淡入。当我们想要重用这个ViewHolder 的时候,如果动画刚结束,ViewHolder 还没来得及回收,传递给RecyclerView的就是一个已经存在的ViewHolder ,这就导致了以上的问题。
虽然看人家这么说是这个原因,但是没看过源码还是搞不明白,等有空把RecyclerView的源码研究研究再说吧。
My Solution
根据 samebug上推荐的答案,将notifyItemRemoved()方法替换成了notifyDataSetChanged(),bug解决。
|