如何将扩展功能用作Room数据库的TypeConverter方法?

时间:2019-02-28 10:00:09

标签: android kotlin android-room

我想知道是否有人找到使用Room数据库时将kotlins扩展功能用作TypeConverter方法的方法。该代码看起来非常干净,但是我无法找到将转换器添加到RoomDatabase转换器数组中的方法:

enum class Status(val code: Int) {
    ACTIVE(0), INACTIVE(1), COMPLETED(2)
}

@TypeConverter
fun Status.toInt() : Int = this.code // This could be shorter I know

@TypeConverter
fun Int.toStatus() : Status = when(this) { // This could also be shorter
    Status.ACTIVE.code -> Status.ACTIVE
    Status.INACTIVE.code -> Status.INACTIVE
    Status.COMPLETED.code -> Status.COMPLETED
    else -> {
        Timber.e("Could not recognize Status")
        throw IllegalArgumentException("Could not recognize Status")
    }
}

即使测试看起来也非常优雅:

class SampleConverterTest {

    @Test
    fun fromIntToActiveStatus() {
        assertThat(Status.ACTIVE.toInt(), `is`(Status.ACTIVE.code))
    }

    @Test
    fun fromIntToInactiveStatus() {
        assertThat(Status.INACTIVE.toInt(), `is`(Status.INACTIVE.code))
    }

    @Test
    fun fromIntToCompletedStatus() {
        assertThat(Status.COMPLETED.toInt(), `is`(Status.COMPLETED.code))
    }

    @Test
    fun fromActiveStatusToInt() {
        assertThat(Status.ACTIVE.fromInt(), `is`(Status.ACTIVE))
    }

    @Test
    fun fromInactiveStatusToInt() {
        assertThat(Status.INACTIVE.fromInt(), `is`(Status.INACTIVE))
    }

    @Test
    fun fromCompletedStatusToInt() {
        assertThat(Status.COMPLETED.fromInt(), `is`(Status.COMPLETED))
    }
}

我对java kotlin互操作不是很熟悉,但是有什么办法可以将这些扩展名用作您的TypeConverters

编辑:

当@Luksprog在回答中指出时,Status.fromInt()扩展方法不是正确的转换器方法。相反,它必须是Int的扩展名。我已编辑问题以显示此内容。

1 个答案:

答案 0 :(得分:1)

首先,扩展方法(fromInt())之一不是真正的转换器方法。对于该方法,Room希望使用(java)形式的方法:

static Status fromInt(int code){...}

但是Kotlin编译器会生成(在Java中)类似

static Status fromInt(Status obj){...}

Room不知道如何使用此方法,它将数据库中的int转换为您的Status字段。

第二,按照目前的形式,这两种扩展方法几乎没有用。一个是Status.ACTIVE.code的别名,另一个将只是返回在其上被调用的实例。

您不能将这些方法用于TypeConverters接口,因为该接口需要一个将所需的静态方法分组的类引用。您无法在kotlin中访问由kotlin编译器生成的java类(包含方法),因此无法在数据库上使用它。

如果您想保留当前的扩展方法,但又要创建所需的类型转换器方法,则可以使用如下所示的间接方法:

fun Status.toInt(): Int = StatusConverters.toInt(this)

fun Status.fromInt(): Status = StatusConverters.fromInt(this.code)

object StatusConverters {
    @TypeConverter
    @JvmStatic
    fun toInt(status: Status): Int = status.code // This could be shorter I know

    @TypeConverter
    @JvmStatic
    fun fromInt(code: Int): Status = when (code) { // This could also be shorter
       Status.ACTIVE.code -> Status.ACTIVE
       Status.INACTIVE.code -> Status.INACTIVE
       Status.COMPLETED.code -> Status.COMPLETED
       else -> {
            Timber.e("Could not recognize Status")
            throw IllegalArgumentException("Could not recognize Status")
       }
    }
}