Search code examples
enumskotlinandroid-room

Android Room type convert multiple enum types


I am writing a type converter for my Room database. I have a couple custom enum classes and I want to convert all of them to its ordinals when stored in the database. So, instead of writing the following for every single class, is there any way to simplify it (such as pass in a generic enum type)?

class Converter {

    @TypeConverter
    fun toOrdinal(type: TypeA): Int = type.ordinal

    @TypeConverter
    fun toTypeA(ordinal: Int): TypeA = TypeA.values().first { it.ordinal == ordinal }

    @TypeConverter
    fun toOrdinal(type: TypeB): Int = type.ordinal

    @TypeConverter
    fun toTypeB(ordinal: Int): TypeB = TypeB.values().first { it.ordinal == ordinal }

    ...
}

Solution

  • As discussed here, Room can't handle generic converters at the moment. I think the best you can do is create extensions that make writing these enum converters quicker:

    @Suppress("NOTHING_TO_INLINE")
    private inline fun <T : Enum<T>> T.toInt(): Int = this.ordinal
    
    private inline fun <reified T : Enum<T>> Int.toEnum(): T = enumValues<T>()[this]
    

    This would simplify each pair of converters to this code:

    @TypeConverter fun myEnumToTnt(value: MyEnum) = value.toInt()
    @TypeConverter fun intToMyEnum(value: Int) = value.toEnum<MyEnum>()
    

    Or if you might be storing null values:

    @TypeConverter fun myEnumToTnt(value: MyEnum?) = value?.toInt()
    @TypeConverter fun intToMyEnum(value: Int?) = value?.toEnum<MyEnum>()