NullPointerException - 尝试在空对象引用上调用虚拟方法 RecyclerView$ViewHolder.shouldIgnore()'



一些开发人员报告说,自从升级到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

相关内容

最新更新