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

时间:2016-03-04 00:54:56

标签: android android-support-library android-recyclerview

自从升级到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.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中的错误,还是开发人员做错了什么?

6 个答案:

答案 0 :(得分:6)

这似乎是由于RecyclerView中的一个错误引起的,该错误是在23.2.0中引入的。该错误已被报告here,我解释了我认为导致comment #5错误的错误。

以下是我的解释,为了历史目的而复制到这里以便于参考:

  

我找到了这个问题的根源。内   RecyclerView.dispatchLayoutStep3(),有一个for循环," for(int i =   0;我<计数; ++ i)",其中count是基于   mChildHelper.getChildCount()。虽然这个迭代正在发生,但是   由ChildHelper管理的集合由。修改   ChildHelper.hideViewInternal(),返回null   从第3050行的mChildHelper.getChildAt()调用   RecyclerView,反过来导致返回null   getChildViewHolderInt()在同一行代码上(RecyclerView:3050)。

     

这是导致修改的方法调用链   打破了for循环的完整性:

     

dispatchLayoutStep3() - > animateChange() - > addAnimatingView() - >   hide() - > hideViewInternal()

     

当ChildHelper将子参数添加到其mHiddenViews集合时,   它违反了for循环的完整性   dispatchLayoutStep3()。

     

我看到了两个解决方法:

     

1)在RecyclerView中禁用更改动画

     

2)降级到23.1.1,这不是一个问题

答案 1 :(得分:5)

在我的情况下,错误是因为我将新的RecyclerView.LayoutParams设置为项目的rootview

然后我意识到RecyclerView项目视图实际上将他们的ViewHolders存储在自定义的LayoutParams类中。 因此,当我重置LayoutParams ViewHolder时,引用将永远消失。这会导致NullPointerException以后崩溃。

我停止将RecyclerView.LayoutParams设置为项目rootView后,问题就消失了。 :)

<强>因此。停止在ViewHolder中执行此操作:

RecyclerView.LayoutParams params = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
itemRoot.setLayoutParams(params);

答案 2 :(得分:3)

如果您绝对需要修改布局参数,可以使用默认的项目布局参数,如下所示:

    ViewGroup.LayoutParams params = itemView.getLayoutParams();
    params.height=xx;
    params.width= xx;
    params.yyyy = xxx;
    itemView.setLayoutParams(params);

答案 3 :(得分:1)

我刚才遇到了这个例外,我通过将framgent更改为FragmentLayout来解决此问题。

我的适配器在fragment参数中使用了一些数据,xml中的using fragment没有填充数据,因此发生了错误。

只需在此发布,也许对某人有用。

答案 4 :(得分:0)

即使使用RecyclerView 27.1.1版本,我也遇到了这个问题。 我的项目中有以下代码:

    recyclerView.setLayoutManager(mLayoutManager);
    SimpleItemAnimator itemAnimator = new DefaultItemAnimator();
    itemAnimator.setSupportsChangeAnimations(false);
    recyclerView.setItemAnimator(itemAnimator);
    LayoutInflater inflater = LayoutInflater.from(getContext());

在将Animator添加到RecyclerView之后,我已对其进行了修复,即此代码开始看起来如下:

    recyclerView.setLayoutManager(mLayoutManager);
    LayoutInflater inflater = LayoutInflater.from(getContext());

答案 5 :(得分:0)

请检查您的 recyclerview 不在孩子的layout.xml