RecyclerView点击触发NullPointerException崩溃排查求助
RecyclerView空指针崩溃排查求助
崩溃基本信息
- 涉及设备:
- Infinix-X688B(Android 11,SDK 30)
- samsung a3core(Android 13,SDK 33)
- TECNO-BG6(Android 13,SDK 33)
- POCO aresin(Android 13,SDK 33)
- 崩溃频率:约每三天或更久出现一次,应用日活跃用户超1000人
- 崩溃报错:
java.lang.NullPointerException - 怀疑关联代码:
public void onBindViewHolder(@NonNull RowViewHolder holder, int position) { ...... holder.itemView.setOnClickListener(v -> { int old_postion =-1; old_postion = position; if(old_postion == position){ int colorBlue = ContextCompat.getColor(holder.itemView.getContext(), R.color.black); v.setBackgroundColor(colorBlue); notifyItemChanged(old_postion); } }); }
- 崩溃堆栈:
Exception java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.ViewGroup$LayoutParams android.view.View.getLayoutParams()' on a null object reference at androidx.recyclerview.widget.RecyclerView$LayoutManager.getPosition (RecyclerView.java) at androidx.recyclerview.widget.LinearLayoutManager.findReferenceChild (LinearLayoutManager.java) at androidx.recyclerview.widget.LinearLayoutManager.findFirstReferenceChild (LinearLayoutManager.java) at androidx.recyclerview.widget.LinearLayoutManager.findReferenceChildClosestToStart (LinearLayoutManager.java:7) at androidx.recyclerview.widget.LinearLayoutManager.updateAnchorFromChildren (LinearLayoutManager.java:7) at androidx.recyclerview.widget.LinearLayoutManager.updateAnchorInfoForLayout (LinearLayoutManager.java:7) at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren (LinearLayoutManager.java:7) at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2 (RecyclerView.java) at androidx.recyclerview.widget.RecyclerView.onMeasure (RecyclerView.java:2) at android.view.View.measure (View.java:26488) at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7109) at android.widget.LinearLayout.measureChildBeforeLayout (LinearLayout.java:1552) at android.widget.LinearLayout.measureVertical (LinearLayout.java:842) at android.widget.LinearLayout.onMeasure (LinearLayout.java:721) at android.view.View.measure (View.java:26488) at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure (ConstraintLayout.java:23) at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure (ConstraintWidgetContainer.java:7) at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.layout (ConstraintWidgetContainer.java:43) at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solveLinearSystem (BasicMeasure.java:8) at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solverMeasure (BasicMeasure.java:62) at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure (ConstraintWidgetContainer.java:62) at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem (ConstraintLayout.java:62) at androidx.constraintlayout.widget.ConstraintLayout.onMeasure (ConstraintLayout.java:62) at android.view.View.measure (View.java:26488) at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7109) at android.widget.FrameLayout.onMeasure (FrameLayout.java:194) at androidx.appcompat.widget.ContentFrameLayout.onMeasure (ContentFrameLayout.java) at android.view.View.measure (View.java:26488) at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7109) at android.widget.LinearLayout.measureChildBeforeLayout (LinearLayout.java:1552) at android.widget.LinearLayout.measureVertical (LinearLayout.java:842) at android.widget.LinearLayout.onMeasure (LinearLayout.java:721) at android.view.View.measure (View.java:26488) at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7109) at android.widget.FrameLayout.onMeasure (FrameLayout.java:194) at android.view.View.measure (View.java:26488) at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7109) at android.widget.LinearLayout.measureChildBeforeLayout (LinearLayout.java:1552) at android.widget.LinearLayout.measureVertical (LinearLayout.java:842) at android.widget.LinearLayout.onMeasure (LinearLayout.java:721) at android.view.View.measure (View.java:26488) at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7109) at android.widget.FrameLayout.onMeasure (FrameLayout.java:194) at com.android.internal.policy.DecorView.onMeasure (DecorView.java:762) at android.view.View.measure (View.java:26488) at android.view.ViewRootImpl.performMeasure (ViewRootImpl.java:4079) at android.view.ViewRootImpl.measureHierarchy (ViewRootImpl.java:2794) at android.view.ViewRootImpl.performTraversals (ViewRootImpl.java:3059) at android.view.ViewRootImpl.doTraversal (ViewRootImpl.java:2510) at android.view.ViewRootImpl$TraversalRunnable.run (ViewRootImpl.java:9266) at android.view.Choreographer$CallbackRecord.run (Choreographer.java:1234) at android.view.Choreographer$CallbackRecord.run (Choreographer.java:1242) at android.view.Choreographer.doCallbacks (Choreographer.java:902) at android.view.Choreographer.doFrame (Choreographer.java:835) at android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:1217) at android.os.Handler.handleCallback (Handler.java:942) at android.os.Handler.dispatchMessage (Handler.java:99) at android.os.Looper.loopOnce (Looper.java:201) at android.os.Looper.loop (Looper.java:288) at android.app.ActivityThread.main (ActivityThread.java:8194) at java.lang.reflect.Method.invoke at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:703) at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:911)
排查情况
已检查RecyclerView Adapter代码,未发现明显异常,但无法定位崩溃具体原因,请求协助排查。
排查思路
- 避免重复设置点击事件:每次
onBindViewHolder调用都会给itemView添加新的点击监听,可能导致多次触发notifyItemChanged,引发布局异常。建议在ViewHolder构造方法中设置点击事件,通过getAdapterPosition()获取当前位置(该方法能实时反映视图对应的数据集位置,比onBindViewHolder的position更可靠)。
修改示例:
class RowViewHolder extends RecyclerView.ViewHolder { public RowViewHolder(@NonNull View itemView) { super(itemView); itemView.setOnClickListener(v -> { int currentPosition = getAdapterPosition(); if (currentPosition != RecyclerView.NO_POSITION) { int colorBlack = ContextCompat.getColor(itemView.getContext(), R.color.black); v.setBackgroundColor(colorBlack); notifyItemChanged(currentPosition); } }); } }
- 避免布局阶段触发UI更新:当前点击事件中直接调用
notifyItemChanged会触发RecyclerView重新布局,若此时正处于测量/布局流程(如堆栈显示的RecyclerView.onMeasure),可能导致视图引用为空。可通过post延迟执行更新:
itemView.post(() -> { int currentPosition = getAdapterPosition(); if (currentPosition != RecyclerView.NO_POSITION) { notifyItemChanged(currentPosition); } });
确保线程安全:所有数据集修改和
notifyXXX方法调用必须在主线程执行,后台线程操作可能导致布局时数据不一致,引发空指针。升级RecyclerView版本:该空指针可能是旧版本RecyclerView的已知bug,尝试升级到最新的
androidx.recyclerview:recyclerview依赖,修复潜在的布局逻辑问题。
内容的提问来源于stack exchange,提问作者fekhreddine bouziane
相关产品推荐
相关产品推荐

