Me preguntaba si alguien encontró una manera de usar las funciones de extensión de TypeConverter como métodos de TypeConverter al usar la base de datos de Room. El código se ve súper limpio, pero no he podido encontrar una manera de agregar el convertidor a la matriz de convertidores de 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") } }Incluso las pruebas se ven súper elegantes:
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)) } } No estoy muy familiarizado con la interoperabilidad de Java Kotlin, pero ¿hay alguna forma de tener estas extensiones como sus TypeConverters ?
EDITAR:
Tenga cuidado, como señaló @Luksprog en su respuesta, el método de extensión Status.fromInt() no es un método de conversión correcto. En cambio, tendría que ser una extensión en Int . He editado mi pregunta para mostrar esto.
En primer lugar, uno de los métodos de extensión (fromInt()) no es un método de conversión real. Para ese método, Room espera un método en forma de (en Java):
static Status fromInt(int code){...}sin embargo, el compilador de Kotlin generará (en Java) algo como
static Status fromInt(Status obj){...}Room no sabrá qué hacer con este método que necesita convertir del int en la base de datos a su campo Estado.
En segundo lugar, en su forma actual, esos dos métodos de extensión son bastante inútiles. Uno es un alias para Status.ACTIVE.code y el otro simplemente devolverá la instancia en la que se invocó.
No puede usar esos métodos para la interfaz TypeConverters porque esa interfaz espera una referencia de clase que agrupe los métodos estáticos requeridos. No puede acceder en kotlin a la clase java (que contiene los métodos) que generará el compilador de kotlin, por lo que no puede usarla en la base de datos.
Si desea mantener sus métodos de extensión actuales, pero también crear los métodos de conversión de tipo requeridos, podría usar alguna indirecta como la siguiente:
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") } } }