You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kotlin中获取HashMap值遇类型转换异常,求解决方案

问题原因

你用Gson序列化MutableMap<String, StorageData>存入SharedPreferences时,Gson默认不会保留泛型类型信息,取出时会把Map中的值解析成LinkedTreeMap(Gson内置的Map实现类),而非你定义的StorageData实体类,直接强转就会触发ClassCastException。

解决方法

方案1:用TypeToken指定泛型类型解析

从SharedPreferences读取数据时,通过TypeToken明确告知Gson目标泛型类型,避免自动解析成LinkedTreeMap:

// 读取存储信息的代码改造
val gson = Gson()
val storageJson = appPreference.getString("storage_info_key", "") ?: ""
// 用TypeToken明确泛型类型
val targetType = object : TypeToken<MutableMap<String, StorageData>>() {}.type
val storageMap: MutableMap<String, StorageData> = gson.fromJson(storageJson, targetType)

// 后续取值无需强转
if (storageMap.isNotEmpty() && storageMap.containsKey(modelNumber)) {
    containerView.apply {
        val storageData = storageMap[modelNumber]
        tv_total.text = storageData?.total
        tv_free.text = storageData?.free
        tv_movie.text = storageData?.movie
        tv_event.text = storageData?.event
    }
}

方案2:封装成含Map的实体类

定义一个包裹Map的实体类,让Gson能准确识别嵌套类型,避免泛型丢失:

// 定义包裹类
data class StorageWrapper(val storageMap: MutableMap<String, StorageData>)

存入时序列化这个包裹类:

val wrapper = StorageWrapper(yourOriginalStorageMap)
val json = gson.toJson(wrapper)
appPreference.edit().putString("storage_info_key", json).apply()

取出时直接解析成包裹类:

val json = appPreference.getString("storage_info_key", "") ?: ""
val wrapper = gson.fromJson(json, StorageWrapper::class.java)
val storageMap = wrapper.storageMap

方案3:手动转换LinkedTreeMap到StorageData

如果无法修改原有存储逻辑,可手动将LinkedTreeMap的键值对映射到StorageData实体:

if (appPreference.getStorageInfo().isNotEmpty() && appPreference.getStorageInfo().containsKey(modelNumber)) {
    val linkedHashMap = appPreference.getStorageInfo()
    val treeMap = linkedHashMap[modelNumber] as LinkedTreeMap<*, *>
    // 手动映射属性,确保key与StorageData属性名一致
    val storageData = StorageData(
        total = treeMap["total"] as? String,
        free = treeMap["free"] as? String,
        movie = treeMap["movie"] as? String,
        event = treeMap["event"] as? String
    )
    containerView.apply {
        tv_total.text = storageData.total
        tv_free.text = storageData.free
        tv_movie.text = storageData.movie
        tv_event.text = storageData.event
    }
}

注意:此方案依赖LinkedTreeMap的key与StorageData属性名完全匹配,且类型兼容,否则会出现空值或转换异常。

内容的提问来源于stack exchange,提问作者MARSH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 18:12:39