Room error in Android: TypeConverter not recognized for enumeration list

The Room library does not recognize the TypeConverter that I created for the List enumerations. However, when I change this to an ArrayList enumerations, it works fine. Does anyone know why and what can I do to make this work with List ? (Using List in Kotlin is simpler, and I really don't want to convert back and forth to ArrayList just because of this).

Here is my code:

My model:

 @Entity data class Example(@PrimaryKey val id: String?, val name: String, var days: List<DayOfWeek>?) 

DayOfWeek is an enumeration:

 enum class DayOfWeek { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY; val value: Int get() = ordinal + 1 companion object { private val ENUMS = DayOfWeek.values() fun of(dayOfWeek: Int): DayOfWeek { if (dayOfWeek < 1 || dayOfWeek > 7) { throw RuntimeException("Invalid value for DayOfWeek: " + dayOfWeek) } return ENUMS[dayOfWeek - 1] } } } 

My TypeConverter :

 private const val SEPARATOR = "," class DayOfWeekConverter { @TypeConverter fun daysOfWeekToString(daysOfWeek: List<DayOfWeek>?): String? { return daysOfWeek?.map { it.value }?.joinToString(separator = SEPARATOR) } @TypeConverter fun stringToDaysOfWeek(daysOfWeek: String?): List<DayOfWeek>? { return daysOfWeek?.split(SEPARATOR)?.map { DayOfWeek.of(it.toInt()) } } } 

And I installed it in my DB class as follows:

 @Database(entities = arrayOf(Example::class), version = 1) @TypeConverters(DayOfWeekConverter::class) abstract class AppDatabase : RoomDatabase() { abstract fun exampleDao(): ExampleDao } 

My DAO looks like this:

 @Dao interface ExampleDao { @Query("SELECT * FROM example") fun getAll(): LiveData<List<Example>> @Insert(onConflict = REPLACE) fun save(examples: List<Example>) } 

Error with this code:

 error: Cannot figure out how to save this field into database. You can consider adding a type converter for it. e: e: private java.util.List<? extends com.example.DayOfWeek> days; 

As I said above, if you change the days property to ArrayList<DayOfWeek> (and make changes to ArrayList in DayOfWeekConverter ), then everything will be fine. If anyone can help me figure this out and tell me how I can use List , it will be very useful here, it drives me crazy: /.

+8
android kotlin android-room android-architecture-components
source share
3 answers

For some reason, Room doesn't like the Kotlin List , but when I replaced List with a MutableList , it started working:

 @Entity data class Example(@PrimaryKey val id: String, val name: String, var days: MutableList<DayOfWeek>?) class DayOfWeekConverter { companion object { @TypeConverter @JvmStatic fun daysOfWeekToString(daysOfWeek: MutableList<DayOfWeek>?): String? = daysOfWeek?.map { it.value }?.joinToString(separator = SEPARATOR) @TypeConverter @JvmStatic fun stringToDaysOfWeek(daysOfWeek: String?): MutableList<DayOfWeek>? = daysOfWeek?.split(SEPARATOR)?.map { DayOfWeek.of(it.toInt()) }?.toMutableList() } } 

This is not an ideal solution, but I hope you can learn more about it.

Also you need to change @PrimaryKey so that it is not null

+1
source share

We have no way to store and retrieve a List enumeration without a list of arrays. The number does not support it. But if you want to avoid using a list of arrays, you can create a ListDayOfWeek object with a list - this is an attribute. I tried, and everything is in order. If you need a code, answer here. I will send it.

-one
source share

You cannot store it in your database. Better build something like this and save it as an int:

 enum class DaysOfWeek(var bitValue: Int) { Monday(64), Tuesday(32), Wednesday(16), Thursday(8), Friday(4), Saturday(2), Sunday(1); } 

Finally, your utility performs the function of converting from / to enumeration.

 fun daysToBitValue(days: EnumSet<DaysOfWeek>): Int { var daysBitValue = 0 for (`val` in days) daysBitValue += `val`.bitValue return daysBitValue } private fun fromBitValues(origBitMask: Int): EnumSet<DaysOfWeek> { val ret_val = EnumSet.noneOf(DaysOfWeek::class.java) var bitMask = origBitMask for (`val` in DaysOfWeek.values()) { if (`val`.bitValue and bitMask == `val`.bitValue) { bitMask = bitMask and `val`.bitValue.inv() ret_val.add(`val`) } } if (bitMask != 0) { throw IllegalArgumentException(String.format(Locale.getDefault(), "Bit mask value 0x%X(%d) has unsupported bits 0x%X. Extracted values: %s", origBitMask, origBitMask, bitMask, ret_val)) } return ret_val } 

Now you can either save the int and get the days of the week later:

 @Entity data class Example(@PrimaryKey val id: String?, val name: String, var days: Int = 0) 

or you use an enumeration and write a suitable typeconverter for this.

 @Entity data class Example(@PrimaryKey val id: String?, val name: String, var days: EnumSet<DaysOfWeek>?) class DayOfWeekConverter { @TypeConverter fun daysOfWeekToString(daysOfWeek: EnumSet<DayOfWeek>?) = daysOfWeek?.let{ YourUtilities.daysToBitValue(it) } @TypeConverter fun intToDaysOfWeek(daysOfWeek: Int?) = daysOfWeek?.let { YourUtilities.fromBitValues(it) } } 

You can scroll through the listing and receive all days using

 for (aDaysOfWeekEnumSet in daysOfWeekEnumSet) info{ "day = ${aDaysOfWeekEnumSet.name"} 

The code is not verified because im is not on my computer, but this should show a concept that works better than saving an enum (which is just an alias for a predefined value!)

-one
source share

All Articles