Android:如何为Kotlin中的所有对象列表创建类型转换器(for Room)

时间:2017-10-05 11:59:37

标签: android database generics kotlin android-room

我在我的项目中使用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
}

问题只是我有一大堆需要转换的不同类型的List,所以目前我只是为每种类型复制这个代码。我想使用泛型,但到目前为止还没有弄清楚如何去做。

例如使用以下内容:

@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使用泛型?

5 个答案:

答案 0 :(得分:0)

我刚试过这个,似乎为你要找的东西做了基础。由您来调整功能以满足您的需求,但这应该让您前进: 参考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
    }

答案 1 :(得分:0)

我有同样的问题。仅用于转换listToString的部分解决方案

@TypeConverter
@JvmStatic
fun listToString(list: List<*>?): String? = list.let {
    val gson = GsonBuilder().serializeNulls().create()

    gson.toJson(it)
}

答案 2 :(得分:0)

我试图使用标记器接口将类转换为标记器,反之亦然,但这没有用。我尝试了大多数Java扩展的Object类,但是没有用。我认为答案是您不能在房间类型转换器中使用Generic。

答案 3 :(得分:0)

这样的东西对模板不起作用吗?

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
    }
}

答案 4 :(得分:-1)

好吧,基本上类型转换器的主要思想是数据库不能将对象作为参数读取。因此,您必须采用两种方法,第一种是使用db内部的join关系手动进行操作,也可以使用type转换器。 类型转换器如何工作? 它很简单,只需将您的对象转换为JSON String并将其保存为字符串。 在您遇到的问题中,您必须在实体之前添加注释

private class YourDTO(
        @TypeConverters(DateConverter.class)
         Date date

在DateConverter类中

@TypeConverter
public static Long toTimestamp(Date date) {
    return date == null ? null : date.getTime();
}