Intent传值初次接收为null引发NumberFormatException问题求助
看起来你遇到的核心问题是:首次启动ViewSessionDataActivity时,通过getIntent()获取的所有Extra参数都是null,导致调用Long.parseLong(time)时触发NumberFormatException;但点击错误弹窗让Activity重启后,又能正常拿到Intent传递的正确数据。
问题根源
从日志和代码来看,你是在Service中使用FLAG_ACTIVITY_NEW_TASK启动Activity。如果ViewSessionDataActivity已经存在于当前任务栈中,Android默认会复用已有的Activity实例,而不是创建新实例——这时候getIntent()返回的是第一次启动该Activity时的旧Intent(大概率是没有携带Extra的空Intent),所以初次获取时全为null;而错误弹窗导致Activity重启后,系统会创建新实例,此时才会接收新传递的Intent数据。
解决方案
方案1:处理Activity复用场景,更新Intent
在ViewSessionDataActivity中重写onNewIntent()方法,确保复用实例时能拿到最新的Intent,同时抽离数据初始化逻辑做统一处理:
private DateFormat dateFormat; private TextView distance_view, speed_view, time_view; private String distance, speed; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_view_session_data); dateFormat = new SimpleDateFormat("dd/MM/yyy 'at' hh:mm aaa"); // 初始化View distance_view = findViewById(R.id.distance); speed_view = findViewById(R.id.speed); time_view = findViewById(R.id.time); save_button = findViewById(R.id.save_button); delete_button = findViewById(R.id.delete_button); // 从Intent加载数据 initDataFromIntent(getIntent()); } // 重写onNewIntent,接收新的Intent并更新 @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); // 替换旧的Intent为新传递的Intent initDataFromIntent(intent); // 重新加载数据 } // 抽离数据初始化逻辑,统一处理 private void initDataFromIntent(Intent intent) { if (intent == null) { Log.w("ViewSessionData", "Intent is null, skip data loading"); return; } distance = intent.getStringExtra("DISTANCE"); String time = intent.getStringExtra("TIME"); speed = intent.getStringExtra("SPEED"); Log.d("distance =", "" + distance); Log.d("time1 =", "" + time); Log.d("speed =", "" + speed); // 强制非空校验,避免崩溃 if (time == null || time.trim().isEmpty()) { time_view.setText("00:00"); distance_view.setText("0.00 Km"); speed_view.setText("0.00 m/s"); return; } try { final long time1 = Long.parseLong(time); final String dateStr = dateFormat.format(Calendar.getInstance().getTime()); Log.d("distance","" + distance); Log.d("time","" + time1); Log.d("speed","" + speed); Log.d("date", dateStr); // 更新UI distance_view.setText(distance + " Km"); speed_view.setText(speed + " m/s"); time_view.setText(getDurationBreakdown(time1)); } catch (NumberFormatException e) { Log.e("ViewSessionData", "Failed to parse time: " + time, e); time_view.setText("Invalid time"); } }
方案2:启动时强制创建新实例
如果你不需要复用ViewSessionDataActivity的旧实例,可以在发送Intent时添加FLAG_ACTIVITY_CLEAR_TOP标志,确保销毁栈中已存在的实例并创建新实例:
public void onLogEnd(){ // ... 你的原有计算逻辑 ... Intent i = new Intent(); i.setClass(MyBoundService.this, ViewSessionDataActivity.class); // 组合FLAG,确保创建新实例 i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); i.putExtra("DISTANCE", convertDistance(distance)); i.putExtra("TIME", time1); i.putExtra("SPEED", formatSpeed(avgSpeed)); startActivity(i); }
方案3:发送端确保Extra非空
检查convertDistance()和formatSpeed()方法,确保它们返回的字符串永远不为null。例如:
private String convertDistance(Float distance) { if (distance == null) { return "0.00"; } // 你的原有转换逻辑 return String.format("%.2f", distance / 1000); } private String formatSpeed(double avgSpeed) { return String.format("%.2f", avgSpeed); }
总结
最稳妥的方式是方案1 + 方案3:既处理Activity复用导致的Intent旧数据问题,又通过非空校验和异常捕获避免崩溃,同时确保发送端传递的Extra不会为null。
内容的提问来源于stack exchange,提问作者Tristan O'Keefe

