首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android SharedPreferences 解析長整型異常:空字符串導致 NumberFormatException

     編輯:程式設計綜合問答

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))); // 這裡拋異常
    }
}

根本原因

  1. 默認值為 null:getString(key, null) 返回 null,但 if (content != null) 判斷通過
  2. 空字符串分割:若存儲值為 "",split(",") 返回 [""](長度 1 的數組,元素為空串)
  3. 解析空串:Long.parseLong("") 拋出 NumberFormatException

修正方案

1. 完善非空判斷


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);
            }
        }
    }
}

2. 存儲時保證格式


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 邏輯有誤,可能導致數據截斷或崩潰。

3. 使用 JSON 序列化(推薦)


// 存儲
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));

優點:類型安全、自動處理空列表、擴展性強(可存儲對象)。

最佳實踐總結

  • SharedPreferences 讀取時永遠提供非 null 默認值(如 "" 或 "[]")
  • 解析前檢查字符串非空
  • 捕獲 NumberFormatException 防止單條錯誤數據導致整體失效
  • 複雜數據優先考慮 JSON/ProtoBuf 序列化
  • 使用 apply() 替代 commit() 異步寫入提升性能
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved