Android:如何使 Kotlin 中所有对象列表的类型转换器(用于 Room)通用
Posted
技术标签:
【中文标题】Android:如何使 Kotlin 中所有对象列表的类型转换器(用于 Room)通用【英文标题】:Android: How to make type converters (for Room) generic for all List of objects in Kotlin 【发布时间】:2017-10-05 11:59:36 【问题描述】:我在我的项目中使用 Room 作为本地数据库解决方案。 对于某个对象类型的每个列表,我已将类型转换器添加到项目中,因此类型转换器看起来像这样:
@TypeConverter
fun convertListToString(video: List<VideoType>): String
val videoArray = arrayOfNulls<VideoType>(video.size)
for (i in 0..video.size - 1)
videoArray[i] = video[i]
var str = ""
val gson = Gson()
for (i in videoArray.indices)
val jsonString = gson.toJson(videoArray[i])
str = str + jsonString
if (i < videoArray.size - 1)
str = str + strSeparator
return str
@TypeConverter
fun convertStringToList(videoString: String): List<VideoType>
val videoArray = videoString.split(strSeparator.toRegex()).dropLastWhile it.isEmpty() .toTypedArray()
val videos = ArrayList<VideoType>()
val gson = Gson()
for (i in 0 until videoArray.size - 1)
videos.add(gson.fromJson(videoArray[i], VideoType::class.java))
return videos
唯一的问题是我有一大堆需要转换的不同类型的列表,所以目前我只是为每种类型复制这段代码。我想使用泛型,但到目前为止还没有弄清楚如何去做。
例如使用类似的东西:
@TypeConverter
inline fun <reified T> convertStringToList(string: String): List<T>
val objectArray = string.split(strSeparator.toRegex()).dropLastWhile it.isEmpty() .toTypedArray()
val objects = ArrayList<T>()
val gson = Gson()
for (i in 0 until objectArray.size - 1)
objects.add(gson.fromJson(objectArray[i], T::class.java))
return objects
不起作用并导致 android Studio 出现编译错误,告诉我一个错误提示:类型转换器必须是公共的
任何人知道如何为我的 Room TypeConverter 使用泛型?
【问题讨论】:
很好奇你是否能够解决这个问题。如果是这样,您介意为其他人回答您的问题吗? @fawaad 嗨..不,我无法以通用方式解决它。我也很好奇是否有人找到了方法...... 我也有同样的问题,如果你解决了,请发布你的解决方案 @SaurabhKhare 尚未找到通用解决方案。到目前为止需要为每个列表添加类型转换器:( 嗨,如果您不介意的话,您可以在 GitHub 存储库中分享相关代码,我想运行并测试它。 @RikvanVelzen 【参考方案1】:这样的东西不能用于模板吗?
abstract class Converters<T>
@TypeConverter
fun mapListToString(value: List<T>): String
val gson = Gson()
val type = object : TypeToken<List<T>>() .type
return gson.toJson(value, type)
@TypeConverter
fun mapStringToList(value: String): List<T>
val gson = Gson()
val type = object : TypeToken<List<T>>() .type
return gson.fromJson(value, type)
// create
class UserConverter : Converters<User>()
// usage
@TypeConverters(UserConverter::class)
abstract class TestDatabase : RoomDatabase()
abstract fun userDao(): UserDao
或者从当前示例中,如果我这样做会怎样
@TypeConverter
fun <T> mapStringToList(inputString: String): List<T>
val array = inputString
.split(strSeparator.toRegex())
.dropLastWhile it.isEmpty()
.toTypedArray()
val result = mutableListOf<T>()
val gson = Gson()
// ? ----
val type = object : TypeToken<List<T>>() .type
// ----
return array.fold(result) acc, item ->
acc.add(gson.fromJson(item, type))
acc
【讨论】:
【参考方案2】:我也有同样的问题。仅用于转换 listToString 的部分解决方案
@TypeConverter
@JvmStatic
fun listToString(list: List<*>?): String? = list.let
val gson = GsonBuilder().serializeNulls().create()
gson.toJson(it)
【讨论】:
【参考方案3】:我尝试使用标记接口将类转换为标记,反之亦然,但没有成功。我尝试了大多数 Java 扩展的 Object
类,但它不起作用。我认为答案是您不能在房间类型转换器中使用 Generic。
【讨论】:
【参考方案4】:嗯,基本上类型转换器的主要思想是数据库不能将对象作为参数读取。所以你必须有两种方法第一种是在数据库中使用连接关系手动完成,或者你可以使用类型转换器。 类型转换器如何工作? 这很简单,只需将您的对象转换为 JSON 字符串并将其保存为字符串。 在您的问题中,您必须在实体之前添加注释
private class YourDTO(
@TypeConverters(DateConverter.class)
Date date
在 DateConverter 类中
@TypeConverter
public static Long toTimestamp(Date date)
return date == null ? null : date.getTime();
【讨论】:
【参考方案5】:我刚刚对此进行了测试,似乎可以满足您的需求。您可以根据需要调整功能,但这应该可以帮助您: 参考https://kotlinlang.org/docs/reference/generics.html#generic-functions
fun test()
val list1 = listOf("1", "2")
val list2 = listOf(1, 2, 3)
list1.convertToString()
list2.convertToString()
fun List<Any>.convertToString(): String
var result = ""
val gson = Gson()
for (i in 0.. size - 1)
result += gson.toJson(get(i), get(i).javaClass)
return result
【讨论】:
这可能会解决将任何类型的列表转换为字符串的技巧,但它不能解决将 typeConvertors 与 Room 一起使用的问题。如果我在列表上使用扩展名,我想将其转换为字符串(即使使用@typeConverter 对其进行注释)房间; “无法弄清楚如何将此字段保存到数据库中。”以上是关于Android:如何使 Kotlin 中所有对象列表的类型转换器(用于 Room)通用的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Android 的 Kotlin 中使用 GSON 将 JSON 对象转换为 JSON 数组
如何在 Kotlin Android 中将字符串转换为 JSON 对象 [重复]
如何从 Firebase android kotlin 获取所有具有特定价值的孩子?