my Question is how to store
List<Enum>
in RoomDatabase, so far I find no answer for that.
my Question is how to store
List<Enum>
in RoomDatabase, so far I find no answer for that.
Enum:
public enum HelloEnum {
A,
B,
C
}
Converter:
public class EnumConverter {
@TypeConverter
public List<HelloEnum> storedStringToEnum(String value) {
List<String> dbValues = Arrays.asList(value.split("\\s*,\\s*"));
List<HelloEnum> enums = new ArrayList<>();
for (String s: dbValues)
enums.add(HelloEnum.valueOf(s));
return enums;
}
@TypeConverter
public String languagesToStoredString(List<HelloEnum> cl) {
String value = "";
for (HelloEnum lang : cl)
value += lang.name() + ",";
return value;
}
}
In terms of inserting and fetching your data this will work not questions asked.
@Dao
public interface HelloPojoDao {
@Query("SELECT * FROM helloPojo")
List<HelloPojo> fetchAll();
@Insert
void insertPojo(HelloPojo pojo);
}
I would however point out that filtering by enum becomes a little more tricky now. For example if you want to write a query for fetching objects containing enum.A and enum.B, you will have to build a query that queries a string object for them. In this case "SELECT * FROM pojo WHERE enums contains ' A,' and ' B,'. As such it is better to assign number values to your enums (as @Kuffs answer details), as parsing ints will likely produce less issues than parsing strings.
Hope this resolves your issue. Feel free to ask any questions in the comment section, and happy hunting!
Ok using Kotlin is much simpler, when using name
class EnumTypeConverter {
@TypeConverter
fun restoreEnum(enumName: String): EnumType = EnumType.valueOf(enumName)
@TypeConverter
fun saveEnumToString(enumType: EnumType) = enumType.name
}
Let me show the way of persisting/retrieving it using kotlin.
What restrictions do we have during the operation?
toString
method of list to string, because it may depend on environment we exactly useSo proper implementation in my opinion will look like:
Enumerable
interface which all enum classes persisted to db should implementSo, the Enumerable interface:
/** marks the enum with custom int code for each value */
interface Enumerable {
val code: Int
}
enum example:
enum class PaymentSystemEntity constructor(
override val code: Int
) : Enumerable {
VISA(1),
MASTERCARD(2),
UNKNOWN(0);
companion object {
fun parseFromCode(code: Int): PaymentSystemEntity = values()
.firstOrNull { it.code == code } ?: UNKNOWN
}
}
serialization extensions:
fun <T> List<T>.asString(): String where T : Enum<T>, T : Enumerable = this
.map { it.code }
.joinToString(separator = ",")
fun <T> String.toEnumList(creator: (code: Int) -> T): List<T> where T : Enum<T>, T : Enumerable = this
.split(',')
.map { it.toInt() }
.map { creator(it) }
Sample type converter for enum:
class PaymentSystemTypeConverter {
@TypeConverter
fun paymentSystemsToString(value: List<@JvmSuppressWildcards PaymentSystemEntity>): String =
value.asString()
@TypeConverter
fun stringToPaymentSystems(value: String): List<@JvmSuppressWildcards PaymentSystemEntity> =
value.toEnumList { PaymentSystemEntity.parseFromCode(it) }
}
You may have other types of collections implemented in a same way
Serialise your enums into integers and store those instead.
When retrieving the values, perform the reverse operation.
Both operations are explained in my answer to this question:
Jack Dalton version in Kotlin:
@TypeConverter
fun storedStringListLineType(value: String): List<LineType> {
val dbValues = value.split("\\s*,\\s*".toRegex()).dropLastWhile { it.isEmpty() }
val enums: MutableList<LineType> = ArrayList()
for (s in dbValues)
enums.add(LineType.valueOf(s))
return enums
}
@TypeConverter
fun listLineTypeToStoredString(listLineTypes: List<LineType>): String {
var value = ""
for (lineType in listLineTypes)
value += lineType.name + ","
return value
}