一些开发人员报告说,自从升级到Android Support 23.2.0以来,看到了以下堆栈跟踪:
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.support.v7.widget.RecyclerView$ViewHolder.shouldIgnore()' on a null object reference
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2913)
at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1445)
at android.support.v7.widget.RecyclerView.access$400(RecyclerView.java:144)
at android.support.v7.widget.RecyclerView$1.run(RecyclerView.java:282)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:821)
at android.view.Choreographer.doCallbacks(Choreographer.java:606)
at android.view.Choreographer.doFrame(Choreographer.java:575)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:807)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6895)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
当启用了 RecyclerView 的更改动画并调用相应的 RecyclerView.Adapter 方法 notifyItemInserted()、notifyItemRemoved() 等来指示对适配器管理的列表进行了隔离更改(而不是由 notifyDataSetChanged() 指示的批量更改)时,会发生这种情况。
这是由于RecyclerView中的错误,还是我们开发人员做错了什么?
在我的情况下,错误是由于我在项目的根视图中设置了新的RecyclerView.LayoutParams。
然后我意识到RecyclerView项目视图实际上将其ViewHolder存储在自定义LayoutParams类中。因此,当我重置LayoutParams ViewHolder引用时,它将永远消失。这会导致稍后出现 NullPointerException 崩溃。
在我停止将RecyclerView.LayoutParams设置为项目rootView后,问题就消失了。 :)
所以,停止在你的 ViewHolder 中这样做:
//DON'T DO THAT
RecyclerView.LayoutParams params = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
itemRoot.setLayoutParams(params);
如果绝对需要修改布局参数,可以使用默认的项目布局参数,如下所示:
ViewGroup.LayoutParams params = itemView.getLayoutParams();
params.height=xx;
params.width= xx;
params.yyyy = xxx;
itemView.setLayoutParams(params);
这似乎是由于 RecyclerView 中的一个错误,该错误是在 23.2.0 中引入的。这里报告了该错误,我解释了我认为导致该错误的评论#5中错误的原因。
这是我的解释,出于历史目的和便于参考,这里复制如下:
我找到了这个问题的根源。在 RecyclerView.dispatchLayoutStep3(),有一个 for 循环,"for (int i = 0;我
下面是导致修改的方法调用链 破坏 for 循环的完整性:
dispatchLayoutStep3() -> animateChange() -> addAnimatingView() -> hide() -> hideViewInternal()
当 ChildHelper 将子参数添加到其 mHiddenViews 集合时, 它违反了 for 循环方式的完整性 dispatchLayoutStep3()。
我看到两种解决方法:
1) 在回收器视图中禁用更改动画
2)降级到23.1.1,这不是问题
我遇到了同样的问题RecyclerView$ViewHolder.shouldIgnore()' on a null object reference
当试图通过设置LayoutParams
隐藏RecyclerView
项目的差距
ViewGroup.LayoutParams params = itemView.getLayoutParams();
params.height = 0;
params.width = 0;
itemView.setLayoutParams(params);
并再次显示
ViewGroup.LayoutParams params = itemView.getLayoutParams();
params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
itemView.setLayoutParams(params);
使用itemView.getLayoutParams();
而不是创建新的参数
可能出现此崩溃的另一种情况是在适配器中未正确实现 getItemId
方法的情况下调用setHasStableIds(true)
我刚才遇到了这个异常,我通过将framgent
更改为FragmentLayout
来修复它。
我的适配器在片段参数中使用了一些数据,而 xml 中的使用fragment
没有填充数据,因此发生了错误。
只是在这里发布这个,也许对某人有用。
我也遇到了这个问题,即使使用RecyclerView 27.1.1版本也是如此。我的项目中有以下代码:
recyclerView.setLayoutManager(mLayoutManager);
SimpleItemAnimator itemAnimator = new DefaultItemAnimator();
itemAnimator.setSupportsChangeAnimations(false);
recyclerView.setItemAnimator(itemAnimator);
LayoutInflater inflater = LayoutInflater.from(getContext());
在删除向RecyclerView添加的Animator后,我已经修复了它,即此代码开始如下所示:
recyclerView.setLayoutManager(mLayoutManager);
LayoutInflater inflater = LayoutInflater.from(getContext());
我有这个例外,因为错误地在RecyclerView
中添加了一个嵌套视图。回收器视图不应具有内部视图。删除它修复了它。
请检查您的回收视图是否不在孩子的layout.xml