【问题标题】:How to store ArrayList of Enum in RoomDatabase如何在 RoomDatabase 中存储枚举的 ArrayList
【发布时间】:2017-06-22 11:41:38
【问题描述】:

我的问题是如何存储

List<Enum>

在 RoomDatabase 中, 到目前为止,我没有找到答案。

【问题讨论】:

  • 我建议将“android-room”作为标签添加到您的问题中。
  • 之前找不到 ;),谢谢
  • 我已经发布了我对这个问题的回答,它可以解决问题吗?如果没有,请评论您需要什么。

标签: android android-sqlite android-room


【解决方案1】:

枚举:

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.A 和 enum.B 的对象,则必须构建一个查询来为它们查询字符串对象。在这种情况下,“SELECT * FROM pojo WHERE enums contains 'A,' and 'B,'。因此,最好为您的枚举分配数字值(作为@Kuffs 答案详细信息),因为解析整数可能会产生比解析字符串。

希望这能解决您的问题。欢迎在评论区提出任何问题,祝您狩猎愉快!

【讨论】:

    【解决方案2】:

    使用 name 时,使用 Kotlin 会简单得多

    class EnumTypeConverter {
    
        @TypeConverter
        fun restoreEnum(enumName: String): EnumType = EnumType.valueOf(enumName)
    
        @TypeConverter
        fun saveEnumToString(enumType: EnumType) = enumType.name
    }
    

    【讨论】:

      【解决方案3】:

      让我展示使用 kotlin 持久化/检索它的方式。

      在操作过程中我们有什么限制?

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

      所以在我看来,正确的实现应该是这样的:

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

      那么,Enumerable 接口:

      /** 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】:

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

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

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

        How to match int to enum

        【讨论】:

        • 好的,我认为最好存储为 String "1" , "2", ... 等等,因此我可以存储多个枚举 - 好点。它需要样板文件... hym 有必要吗?
        • 字符串或整数。真的没关系。概念是一样的。
        【解决方案5】:

        在 Kotlin 中的 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
        }
        

        【讨论】:

          猜你喜欢
          • 2015-11-12
          • 2010-09-20
          • 2011-03-28
          • 2019-10-02
          • 2014-09-09
          • 1970-01-01
          • 1970-01-01
          • 2017-01-28
          • 1970-01-01
          相关资源
          最近更新 更多