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
相关产品推荐
相关产品推荐

