You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android RecyclerView在Google Play商店崩溃问题求助

RecyclerView首尾Item背景修改导致崩溃的解决方案

问题背景

开发中使用RecyclerView+Adapter修改首尾Item背景色,应用在Google Play商店出现崩溃,RecyclerView嵌套在NestedScrollView中,尝试网上方案未解决。

崩溃日志

Exception java.lang.NullPointerException:
  at com.jodaland.example.TableAdapter.onBindViewHolder (TableAdapter.java:66)
  at com.jodaland.example.TableAdapter.onBindViewHolder (TableAdapter.java:17)
  at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder (RecyclerView.java:7065)
  at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder (RecyclerView.java:7107)
  at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline (RecyclerView.java:6012)
  at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline (RecyclerView.java:6279)
  at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition (RecyclerView.java:6118)
  at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition (RecyclerView.java:6114)
  at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next (LinearLayoutManager.java:2303)
  at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk (LinearLayoutManager.java:1627)
  at androidx.recyclerview.widget.LinearLayoutManager.fill (LinearLayoutManager.java:1587)
  at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren (LinearLayoutManager.java:665)
  at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2 (RecyclerView.java:4134)
  at androidx.recyclerview.widget.RecyclerView.onMeasure (RecyclerView.java:3540)
  at android.view.View.measure (View.java:27131)
  at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7951)
  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:27131)
  at androidx.core.widget.NestedScrollView.measureChildWithMargins (NestedScrollView.java:1792)
  at android.widget.FrameLayout.onMeasure (FrameLayout.java:194)
  at androidx.core.widget.NestedScrollView.onMeasure (NestedScrollView.java:627)
  at android.view.View.measure (View.java:27131)
  at android.widget.LinearLayout.measureVertical (LinearLayout.java:995)
  at android.widget.LinearLayout.onMeasure (LinearLayout.java:721)
  at android.view.View.measure (View.java:27131)
  at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure (ConstraintLayout.java:811)
  at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure (ConstraintWidgetContainer.java:632)
  at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.layout (ConstraintWidgetContainer.java:733)
  at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solveLinearSystem (BasicMeasure.java:160)
  at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solverMeasure (BasicMeasure.java:291)
  at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure (ConstraintWidgetContainer.java:120)
  at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem (ConstraintLayout.java:1594)
  at androidx.constraintlayout.widget.ConstraintLayout.onMeasure (ConstraintLayout.java:1708)
  at android.view.View.measure (View.java:27131)
  at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7951)
  at android.widget.FrameLayout.onMeasure (FrameLayout.java:194)
  at androidx.appcompat.widget.ContentFrameLayout.onMeasure (ContentFrameLayout.java:145)
  at android.view.View.measure (View.java:27131)
  at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7951)
  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:27131)
  at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7951)
  at android.widget.FrameLayout.onMeasure (FrameLayout.java:194)
  at android.view.View.measure (View.java:27131)
  at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7951)
  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:27131)
  at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7951)
  at android.widget.FrameLayout.onMeasure (FrameLayout.java:194)
  at com.android.internal.policy.DecorView.onMeasure (DecorView.java:1173)
  at android.view.View.measure (View.java:27131)
  at android.view.ViewRootImpl.performMeasure (ViewRootImpl.java:4187)
  at android.view.ViewRootImpl.measureHierarchy (ViewRootImpl.java:2936)
  at android.view.ViewRootImpl.performTraversals (ViewRootImpl.java:3204)
  at android.view.ViewRootImpl.doTraversal (ViewRootImpl.java:2618)
  at android.view.ViewRootImpl$TraversalRunnable.run (ViewRootImpl.java:9971)
  at android.view.Choreographer$CallbackRecord.run (Choreographer.java:1010)
  at android.view.Choreographer.doCallbacks (Choreographer.java:809)
  at android.view.Choreographer.doFrame (Choreographer.java:744)
  at android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:995)
  at android.os.Handler.handleCallback (Handler.java:938)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loop (Looper.java:246)
  at android.app.ActivityThread.main (ActivityThread.java:8653)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:602)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1130)

Adapter相关代码

@Override
public void onBindViewHolder(TableAdapter.ViewHolder holder, int position) {


    Modal m = this.modalList.get(position);

    if (holder.getItemViewType() == TYPE_HEAD) {

        int colorGreen = ContextCompat.getColor(holder.Time.getContext(),R.color.Green);
        holder.Time.setBackgroundColor(colorGreen);
        holder.Time.setText(m.getTime());

        int colorGray = ContextCompat.getColor(holder.Money.getContext(),R.color.Gray);
        holder.Money.setBackgroundColor(colorGray);
        holder.Money.setText(m.getMoney());

        int colorOchre = ContextCompat.getColor(holder.profit.getContext(),R.color.Ochre);
        holder.profit.setBackgroundColor(colorOchre);
        holder.profit.setText(m.getprofit());

        int colorBlue = ContextCompat.getColor(holder.Sum.getContext(),R.color.Blue);
        holder.Sum.setBackgroundColor(colorBlue);
        holder.Sum.setText(m.getSum());
    }else {
//line 66      holder.Time.setText(m.getTime());
                 holder.Money.setText(m.getMoney());
                 holder.profit.setText(m.getprofit());
                 holder.Sum.setText(m.getSum());
        }
    }

    @Override
    public int getItemCount() {
        int a;
        if (modalList != null && !modalList.isEmpty()) {
            a = modalList.size();
        } else {
            a = 0;
        }
        return a;
    }


    @Override
    public int getItemViewType(int position) {
        if (position == 0 || position == modalList.size()-1 )
            return TYPE_HEAD;
        return TYPE_LIST;
    }

    class ViewHolder extends RecyclerView.ViewHolder {

        public TextView Time;
        public TextView Money;
        public TextView profit;
        public TextView Sum;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            Time = itemView.findViewById(R.id.lbl_time);
            Money = itemView.findViewById(R.id.lbl_money);
            profit = itemView.findViewById(R.id.lbl_profit);
            Sum = itemView.findViewById(R.id.lbl_sum);
        }
    }
}

解决方案

1. 修复ViewHolder控件空指针问题

  • 检查Item布局文件,确保R.id.lbl_time、R.id.lbl_money等ID存在且拼写正确,与ViewHolder中的findViewById调用一一对应。
  • 若为TYPE_HEAD和TYPE_LIST使用了不同布局,必须在onCreateViewHolder中根据视图类型加载对应布局,否则会导致控件找不到:
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view;
    if (viewType == TYPE_HEAD) {
        view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_head_layout, parent, false);
    } else {
        view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_normal_layout, parent, false);
    }
    return new ViewHolder(view);
}

2. 增加数据空判断

在onBindViewHolder中先判断数据是否为空,避免空对象调用方法:

@Override
public void onBindViewHolder(TableAdapter.ViewHolder holder, int position) {
    if (modalList == null || position >= modalList.size()) {
        holder.Time.setText("");
        holder.Money.setText("");
        holder.profit.setText("");
        holder.Sum.setText("");
        return;
    }

    Modal m = modalList.get(position);
    if (m == null) {
        holder.Time.setText("");
        holder.Money.setText("");
        holder.profit.setText("");
        holder.Sum.setText("");
        return;
    }

    // 原有逻辑
    if (holder.getItemViewType() == TYPE_HEAD) {
        int colorGreen = ContextCompat.getColor(holder.Time.getContext(),R.color.Green);
        holder.Time.setBackgroundColor(colorGreen);
        holder.Time.setText(m.getTime() != null ? m.getTime() : "");

        int colorGray = ContextCompat.getColor(holder.Money.getContext(),R.color.Gray);
        holder.Money.setBackgroundColor(colorGray);
        holder.Money.setText(m.getMoney() != null ? m.getMoney() : "");

        int colorOchre = ContextCompat.getColor(holder.profit.getContext(),R.color.Ochre);
        holder.profit.setBackgroundColor(colorOchre);
        holder.profit.setText(m.getprofit() != null ? m.getprofit() : "");

        int colorBlue = ContextCompat.getColor(holder.Sum.getContext(),R.color.Blue);
        holder.Sum.setBackgroundColor(colorBlue);
        holder.Sum.setText(m.getSum() != null ? m.getSum() : "");
    } else {
        holder.Time.setText(m.getTime() != null ? m.getTime() : "");
        holder.Money.setText(m.getMoney() != null ? m.getMoney() : "");
        holder.profit.setText(m.getprofit() != null ? m.getprofit() : "");
        holder.Sum.setText(m.getSum() != null ? m.getSum() : "");
    }
}

3. 修复getItemViewType的边界判断

避免数据变化导致的position越界,增加空判断:

@Override
public int getItemViewType(int position) {
    if (modalList == null || modalList.isEmpty()) {
        return TYPE_LIST;
    }
    // 确保position在合法范围内
    if (position >=0 && (position == 0 || position == modalList.size() -1)) {
        return TYPE_HEAD;
    }
    return TYPE_LIST;
}

4. 适配NestedScrollView嵌套场景

为RecyclerView的LayoutManager开启自动测量,避免嵌套导致的测量异常:

LinearLayoutManager layoutManager = new LinearLayoutManager(context);
layoutManager.setAutoMeasureEnabled(true);
recyclerView.setLayoutManager(layoutManager);
// 设置RecyclerView高度为wrap_content
recyclerView.setLayoutParams(new ViewGroup.LayoutParams(
    ViewGroup.LayoutParams.MATCH_PARENT,
    ViewGroup.LayoutParams.WRAP_CONTENT
));

内容的提问来源于stack exchange,提问作者fekhreddine bouziane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 17:20:53