将MutableMap存入SharedPreferences后读取崩溃问题求助
问题分析与解决
核心问题
报错Expected BEGIN_OBJECT but was NUMBER的本质原因:当SharedPreferences中还不存在stepsRecord这个键时,你调用getString("stepsRecord", "0")会返回默认值"0",而Gson尝试把字符串"0"解析成Map对象时必然失败——因为JSON里0是数字类型,而Map对应的合法JSON格式应该是{}这样的对象结构。
解决方案
1. 修正默认值与空值判断
把读取时的默认值改为null或空字符串,解析前先判断内容是否有效:
val mapYearMonthsString: String? = sharedPreferences.getString("stepsRecord", null) return if (!mapYearMonthsString.isNullOrEmpty()) { // 用TypeToken指定完整泛型类型解析 val type = object : TypeToken<MutableMap<Int, Map<Int, Map<Int, Map<Map<String, Int>, Int>>>>>() {}.type Gson().fromJson(mapYearMonthsString, type) } else { // 返回初始化的空Map HashMap<Int, Map<Int, Map<Int, Map<Map<String, Int>, Int>>>>() }
2. 用TypeToken处理泛型解析
直接用MutableMap::class.java解析会丢失嵌套泛型的类型信息,后续强制类型转换容易引发异常。通过TypeToken可以让Gson准确识别复杂的嵌套Map结构,保证解析结果的类型正确性。
3. 可选:更换存储方式
你的Map嵌套层级极深(Int -> Map<Int, Map<Int, Map<Map<String, Int>, Int>>>),虽然用SharedPreferences能实现存储,但维护和解析成本较高。如果数据量较大或需要后续查询操作,建议改用Room数据库,它更适配结构化数据的持久化,能更好地处理层级关系与类型安全。
内容的提问来源于stack exchange,提问作者Layer891203
相关产品推荐
相关产品推荐

