NullPointerException - 尝试在空对象引用上调用虚方法 RecyclerView$ViewHolder.shouldIgnore()'
NullPointerException - Attempt to invoke virtual method RecyclerView$ViewHolder.shouldIgnore()' on a null object reference
一些开发人员报告说,自从升级到 Android 支持 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.access0(RecyclerView.java:144)
at android.support.v7.widget.RecyclerView.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 的错误,还是我们开发人员做错了什么?
这似乎是由于 23.2.0 中引入的 RecyclerView 中的错误所致。该错误已在 here, and I explained what I think is causing the error in comment #5 上报告。
这是我的解释,出于历史目的和便于参考而复制在这里:
I found the source of this problem. Within
RecyclerView.dispatchLayoutStep3(), there's a for loop, "for (int i =
0; i < count; ++i)", where count is based on
mChildHelper.getChildCount(). While this iteration is occurring, the
collection managed by ChildHelper is modified by
ChildHelper.hideViewInternal(), which results in null being returned
from the call to mChildHelper.getChildAt() on line 3050 of
RecyclerView, which in turn results in null being returned from
getChildViewHolderInt() on the same line of code (RecyclerView:3050).
Here's the chain of method calls that results in the modification that
breaks the integrity of the for loop:
dispatchLayoutStep3() -> animateChange() -> addAnimatingView() ->
hide() -> hideViewInternal()
When ChildHelper adds the child param to its mHiddenViews collection,
it violates the integrity of the for loop way up in
dispatchLayoutStep3().
I see two workarounds for this:
1) Disable change animation in your RecyclerView
2) Downgrade to 23.1.1, where this wasn't a problem
我刚才遇到了这个异常,我通过将 framgent
更改为 FragmentLayout
来修复它。
我的适配器在片段参数中使用了一些数据,在xml中使用fragment
没有填充数据,所以出现了错误。
就post这个,也许对某人有用。
在我的例子中,错误 是因为 我正在将 new RecyclerView.LayoutParams 设置到项目的根视图 中。
然后我意识到 RecyclerView 项目视图实际上将它们的 ViewHolders 存储在自定义 LayoutParams class 中。
因此,当我重置 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 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
的 child 中
我在尝试使用设置 LayoutParams
隐藏 RecyclerView
项的间隙时遇到了同样的问题 RecyclerView$ViewHolder.shouldIgnore()' on a null object reference
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();
而不是创建新参数
另一种可能出现此崩溃的情况是调用 setHasStableIds(true)
时未在适配器
中正确实现 getItemId
方法
我有这个异常,因为在 RecyclerView
中错误地添加了一个嵌套视图。 RecyclerViews 不应该有内部视图。删除它修复它。
一些开发人员报告说,自从升级到 Android 支持 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.access0(RecyclerView.java:144)
at android.support.v7.widget.RecyclerView.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 的错误,还是我们开发人员做错了什么?
这似乎是由于 23.2.0 中引入的 RecyclerView 中的错误所致。该错误已在 here, and I explained what I think is causing the error in comment #5 上报告。
这是我的解释,出于历史目的和便于参考而复制在这里:
I found the source of this problem. Within RecyclerView.dispatchLayoutStep3(), there's a for loop, "for (int i = 0; i < count; ++i)", where count is based on mChildHelper.getChildCount(). While this iteration is occurring, the collection managed by ChildHelper is modified by ChildHelper.hideViewInternal(), which results in null being returned from the call to mChildHelper.getChildAt() on line 3050 of RecyclerView, which in turn results in null being returned from getChildViewHolderInt() on the same line of code (RecyclerView:3050).
Here's the chain of method calls that results in the modification that breaks the integrity of the for loop:
dispatchLayoutStep3() -> animateChange() -> addAnimatingView() -> hide() -> hideViewInternal()
When ChildHelper adds the child param to its mHiddenViews collection, it violates the integrity of the for loop way up in dispatchLayoutStep3().
I see two workarounds for this:
1) Disable change animation in your RecyclerView
2) Downgrade to 23.1.1, where this wasn't a problem
我刚才遇到了这个异常,我通过将 framgent
更改为 FragmentLayout
来修复它。
我的适配器在片段参数中使用了一些数据,在xml中使用fragment
没有填充数据,所以出现了错误。
就post这个,也许对某人有用。
在我的例子中,错误 是因为 我正在将 new RecyclerView.LayoutParams 设置到项目的根视图 中。
然后我意识到 RecyclerView 项目视图实际上将它们的 ViewHolders 存储在自定义 LayoutParams class 中。 因此,当我重置 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 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
我在尝试使用设置 LayoutParams
RecyclerView
项的间隙时遇到了同样的问题 RecyclerView$ViewHolder.shouldIgnore()' on a null object reference
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();
而不是创建新参数
另一种可能出现此崩溃的情况是调用 setHasStableIds(true)
时未在适配器
getItemId
方法
我有这个异常,因为在 RecyclerView
中错误地添加了一个嵌套视图。 RecyclerViews 不应该有内部视图。删除它修复它。