如何优化TypeConverter样板代码?泛型转换器运行时类型解析问题
解决Room中泛型List类型TypeConverter的类型擦除问题
问题背景
现有包含List类型字段的数据类:
data class AddressBook( val persons: List<Person>, val addressList: List<Address> )
为避免重复编写每个List类型的@TypeConverter样板代码,尝试编写泛型转换器类,但因类型擦除导致运行时无法解析泛型参数,@TypeConverters(DataListConverter::class)无法生效:
class DataListConverter<T> { @TypeConverter fun fromList(list: List<T>): String { val gson = Gson() return gson.toJson(list) } @TypeConverter fun toList(data: String): List<T> { val listType = object : TypeToken<List<T>>() {}.type return Gson().fromJson(data, listType) } }
解决方案:通过子类传递具体类型信息
核心思路是利用子类继承泛基类,在子类中传入具体的TypeToken,避免类型擦除导致的类型信息丢失。
- 改造泛型基类
将TypeToken作为构造参数传入,让基类能拿到正确的类型信息:
open class DataListConverter<T>(private val typeToken: TypeToken<List<T>>) { private val gson = Gson() @TypeConverter fun fromList(list: List<T>): String { return gson.toJson(list) } @TypeConverter fun toList(data: String): List<T> { return gson.fromJson(data, typeToken.type) } }
- 创建具体类型的转换器子类
每个List类型只需创建一个极简子类,无需重复编写转换逻辑:
// 对应List<Person>的转换器 class PersonListConverter : DataListConverter<Person>(object : TypeToken<List<Person>>() {}) // 对应List<Address>的转换器 class AddressListConverter : DataListConverter<Address>(object : TypeToken<List<Address>>() {})
- 在Room中注册转换器
在Database或Entity类上添加注解,注册这些具体的转换器:
@TypeConverters(PersonListConverter::class, AddressListConverter::class) @Database(entities = [AddressBook::class], version = 1) abstract class AppDatabase : RoomDatabase() { // DAO定义 }
原理说明
Java/Kotlin的泛型类型擦除会在运行时丢失具体的泛型参数信息,原始泛型类中的TypeToken<List<T>>实际只能表示List<Object>。通过子类继承并传入具体的TypeToken,可以在运行时保留List<Person>或List<Address>的完整类型信息,让Gson能正确解析出目标类型的列表。
内容的提问来源于stack exchange,提问作者Manoj
相关产品推荐
相关产品推荐

