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

Android插入Song列表到Playlist崩溃,Gson抽象类实例化报错

解决方案

问题根源

崩溃的核心原因是Song类中的Uri字段——Android的Uri是抽象类,Gson默认无法实例化抽象类,反序列化时就会抛出JsonIOException。

修复步骤

1. 为Uri自定义Gson TypeAdapter

创建一个适配器类,告诉Gson如何序列化和反序列化Uri:

class UriTypeAdapter : TypeAdapter<Uri>() {
    override fun write(out: JsonWriter, value: Uri?) {
        // 序列化:把Uri转成字符串写入
        out.value(value?.toString())
    }

    override fun read(`in`: JsonReader): Uri? {
        // 反序列化:把字符串转成Uri实例
        val uriString = `in`.nextString()
        return if (uriString.isNotBlank()) Uri.parse(uriString) else null
    }
}

2. 修改DataConverters,使用带适配器的Gson实例

不要每次创建新的Gson对象,复用一个注册了Uri适配器的实例:

class DataConverters {
    // 预配置好Gson实例,注册Uri适配器
    private val gson = GsonBuilder()
        .registerTypeAdapter(Uri::class.java, UriTypeAdapter())
        .create()

    @TypeConverter
    fun toSongList(string: String): List<Song> {
        val listType = object : TypeToken<List<Song>>() {}.type
        return gson.fromJson(string, listType)
    }

    @TypeConverter
    fun fromSongList(list: List<Song>): String {
        return gson.toJson(list)
    }
}

3. 确认Room数据库正确引用转换器

确保你的Room数据库类上添加了@TypeConverters注解:

@Database(entities = [Song::class, Playlist::class], version = 1)
@TypeConverters(DataConverters::class)
abstract class AppDatabase : RoomDatabase() {
    // 定义你的DAO接口
    abstract fun playlistDao(): PlaylistDao
    abstract fun songDao(): SongDao
}

额外说明

  • 不需要额外的ProGuard规则,问题和代码混淆无关,是Gson对抽象类的处理逻辑导致的。
  • 复用Gson实例不仅能解决问题,还能提升性能,避免重复初始化配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 05:43:43