我想知道是否有人找到使用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
的扩展名。我已编辑问题以显示此内容。
答案 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")
}
}
}