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

Android应用点击按钮崩溃:Fragment数据传递计算问题求助

问题解决:Android Fragment跳转崩溃+数据传递无效

一、崩溃原因及修复(NullPointerException)

日志明确报错:java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.widget.Spinner.findViewById(int)' on a null object reference

问题出在FirstFragment的点击事件中,你尝试用未初始化的Spinner s调用findViewById,此时s是null,必然触发崩溃。

修复代码:

将控件初始化逻辑移到onViewCreated方法中(而非点击事件内),使用Fragment的根View查找控件:

public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    // 提前初始化所有需要用到的控件
    s = view.findViewById(R.id.tip);
    brSplice = view.findViewById(R.id.brSpoj);
    brCon = view.findViewById(R.id.brKon);
    cLen = view.findViewById(R.id.duzKabel);
    minPow = view.findViewById(R.id.minPow);
    recPow = view.findViewById(R.id.recPow);

    view.findViewById(R.id.ButIzracun).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            ArrayList<ValAtt> mValAtts = new ArrayList<>();
            Baza baz = new Baza();
            mValAtts = baz.getVA();
            double fibLoss, fibLen, lossBud;

            // 直接使用已初始化的控件
            double sFAtt = mValAtts.get(s.getSelectedItemPosition()).getmAtt();
            fibLoss = kons.getsLoss() * Double.parseDouble(brSplice.getText().toString()) + kons.getcLoss() * Double.parseDouble(brCon.getText().toString()) + Double.parseDouble(cLen.getText().toString()) * sFAtt + kons.getsMarg();
            fibLen = (Double.parseDouble(minPow.getText().toString()) - Double.parseDouble(recPow.getText().toString()) - kons.getsLoss() * Double.parseDouble(brSplice.getText().toString()) - kons.getcLoss() * Double.parseDouble(brCon.getText().toString())) / sFAtt;
            lossBud = fibLoss + Double.parseDouble(minPow.getText().toString()) - Double.parseDouble(recPow.getText().toString());

            // 数据传递逻辑(见下文修复)
            double[] rez = new double[3];
            rez[0] = fibLoss; rez[1] = fibLen; rez[2] = lossBud;

            Bundle bundle = new Bundle();
            bundle.putDoubleArray("key", rez);

            // 带Bundle跳转
            NavHostFragment.findNavController(FirstFragment.this)
                    .navigate(R.id.action_FirstFragment_to_SecondFragment, bundle);
        }
    });
}

二、数据传递无效的修复

你当前的代码逻辑错误:先调用navigate完成跳转,再创建SecondFragment实例并设置Bundle,这完全没用——因为跳转已经由导航组件创建了新的SecondFragment实例,你手动new的实例并未被使用。

修复方式:

将Bundle作为参数传入navigate方法,导航组件会自动将Bundle传递给目标Fragment:

// 先计算结果并创建Bundle
double[] rez = new double[3];
rez[0] = fibLoss; rez[1] = fibLen; rez[2] = lossBud;

Bundle bundle = new Bundle();
bundle.putDoubleArray("key", rez);

// 携带Bundle跳转
NavHostFragment.findNavController(FirstFragment.this)
        .navigate(R.id.action_FirstFragment_to_SecondFragment, bundle);

三、SecondFragment展示异常的修复

你在onCreateView中先初始化了View v并设置了文本,但最后返回的是重新inflate的新View,导致之前设置的文本完全无效。

修复代码:

public View onCreateView(
        LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState
) {
    Bundle bundle = getArguments();
    // 避免bundle为null导致崩溃,增加空判断
    if (bundle != null) {
        rezultat = bundle.getDoubleArray("key");
    } else {
        // 给默认值防止空指针
        rezultat = new double[]{0, 0, 0};
    }

    // 只inflate一次View
    View v = inflater.inflate(R.layout.fragment_second, container, false);

    setTextR1(v);
    setTextR2(v);
    setTextR3(v);

    // 返回初始化好的View
    return v;
}

@SuppressLint("SetTextI18n")
public void setTextR1(View v) {
    r1 = v.findViewById(R.id.textView6);
    r1.setText(Double.toString(rezultat[0]));
}
@SuppressLint("SetTextI18n")
public void setTextR2(View v) {
    r2 = v.findViewById(R.id.textView8);
    r2.setText(Double.toString(rezultat[1]));
}
@SuppressLint("SetTextI18n")
public void setTextR3(View v) {
    r3 = v.findViewById(R.id.textView10);
    r3.setText(Double.toString(rezultat[2]));
}

额外优化建议

  • 避免NumberFormatException:EditText为空时调用Double.parseDouble会崩溃,建议先判断文本是否为空,例如:
    String spliceText = brSplice.getText().toString().trim();
    double spliceNum = spliceText.isEmpty() ? 0 : Double.parseDouble(spliceText);
    
  • 移除assert:正式环境中assert可能被禁用,改用空判断更安全。
  • 复用控件引用:将控件初始化移到onViewCreated,避免每次点击都重新查找控件,提升性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 22:05:30