如何在RoomDatabase中存储Enum的ArrayList

时间:2017-06-22 11:41:39

标签: android android-sqlite android-room

我的问题是如何存储

List<Enum>
RoomDatabase中的

, 到目前为止,我找不到答案。

5 个答案:

答案 0 :(得分:3)

枚举:

public enum HelloEnum {
    A,
    B,
    C
}

转换器:

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;
    }    
}

在插入和获取数据方面,这不会引起问题。

@Dao
public interface HelloPojoDao {

    @Query("SELECT * FROM helloPojo")
    List<HelloPojo> fetchAll();

    @Insert
    void insertPojo(HelloPojo pojo);
}
然而,我会指出,通过enum过滤现在变得有点棘手。例如,如果要编写查询以获取包含enum.A和enum.B的对象,则必须构建一个查询字符串对象的查询。在这种情况下,“SELECT * FROM pojo WHERE enums包含'A,'和'B,'。因此,最好为您的枚举分配数值(如@Kuffs回答详细信息),因为解析整数可能会产生的问题少于解析字符串。

希望这可以解决您的问题。随意在评论部分提出任何问题,并快乐狩猎!

答案 1 :(得分:3)

使用name时,使用Kotlin更简单

class EnumTypeConverter {

    @TypeConverter
    fun restoreEnum(enumName: String): EnumType = EnumType.valueOf(enumName)

    @TypeConverter
    fun saveEnumToString(enumType: EnumType) = enumType.name
}

答案 2 :(得分:0)

将您的枚举序列化为整数并存储它们。

检索值时,请执行相反的操作。

在我对这个问题的回答中解释了这两个操作:

How to match int to enum

答案 3 :(得分:0)

让我展示一下使用kotlin保留/检索它的方法。

手术期间我们有哪些限制?

  • 我们将枚举列表存储为数据库中的字符串字段,因此无法基于它在数据库中进行有效的选择或搜索
  • 我们必须将每个枚举值序列化为字符串并将其反序列化
  • 我们不能将行为基于序数字段以防止由于将来扩展枚举而导致的错误,因此我们需要有一个常量字段来表示每个枚举值
    • 我们无法基于列表的默认toString字符串列表方法,因为它可能取决于我们确切使用的环境

因此,我认为正确的实现应如下所示:

  1. 创建所有持久化到数据库的枚举类的Enumerable接口
  2. 每个枚举类都应具有通过传递序列化参数的创建方法来恢复枚举值
  3. 创建kotlin扩展以序列化/反序列化枚举列表
  4. 为每种枚举类型创建类型转换器

因此,可枚举接口:

/** marks the enum with custom int code for each value */
interface Enumerable {
    val code: Int
}

枚举示例:

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
    }

}

序列化扩展:

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) }

枚举的样本类型转换器:

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) }

}

您可能以相同的方式实现了其他类型的集合

答案 4 :(得分:0)

科特林的杰克·道尔顿(Jack Dalton)版本:

@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
}