Android 應用啟動時讀取 SharedPreferences 存儲的鬧鐘時間列表,若存儲值為空字符串或格式錯誤,Long.parseLong 會拋出 NumberFormatException 導致崩潰。本文分析異常堆棧,提供健壯的解析與存儲方案。
java.lang.RuntimeException: Unable to start activity ...
Caused by: java.lang.NumberFormatException: 空指針錯誤
at java.lang.Long.parseLong(Long.java:552)
at pcAlarm.pack.PCAlarmActivity.readSaveAlarm(PCAlarmActivity.java:XX)
關鍵代碼:
String content = sp.getString(KEY_ALARM_LIST, null);
if (content != null) {
String[] timeString = content.split(",");
for (String string : timeString) {
adapter.add(new AlarmData(Long.parseLong(string))); // 這裡拋異常
}
}
getString(key, null) 返回 null,但 if (content != null) 判斷通過"",split(",") 返回 [""](長度 1 的數組,元素為空串)Long.parseLong("") 拋出 NumberFormatException
String content = sp.getString(KEY_ALARM_LIST, "");
if (!TextUtils.isEmpty(content)) {
String[] timeStrings = content.split(",");
for (String s : timeStrings) {
if (!TextUtils.isEmpty(s)) { // 過濾空串
try {
long time = Long.parseLong(s);
adapter.add(new AlarmData(time));
} catch (NumberFormatException e) {
Log.e(TAG, "Invalid time format: " + s, e);
}
}
}
}
private void saveAlarmList() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < adapter.getCount(); i++) {
sb.append(adapter.getItem(i).getTime());
if (i < adapter.getCount() - 1) sb.append(",");
}
String content = sb.toString(); // 無尾隨逗號
sp.edit().putString(KEY_ALARM_LIST, content).apply();
}
注意:原代碼 substring 邏輯有誤,可能導致數據截斷或崩潰。
// 存儲
List times = new ArrayList<>();
for (int i = 0; i < adapter.getCount(); i++) times.add(adapter.getItem(i).getTime());
String json = new Gson().toJson(times);
sp.edit().putString(KEY_ALARM_LIST, json).apply();
// 讀取
String json = sp.getString(KEY_ALARM_LIST, "[]");
Type type = new TypeToken>(){}.getType();
List times = new Gson().fromJson(json, type);
for (long t : times) adapter.add(new AlarmData(t));
優點:類型安全、自動處理空列表、擴展性強(可存儲對象)。
"" 或 "[]")NumberFormatException 防止單條錯誤數據導致整體失效apply() 替代 commit() 異步寫入提升性能