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
相关产品推荐
相关产品推荐

