2017-06-12 128 views
8

是否可以在新的Android体系结构组件和房间持久性库中将Enum类型用作实体类中的嵌入字段?Android体系结构组件:使用枚举

我的实体(带嵌入式枚举):

@Entity(tableName = "tasks") 
public class Task extends SyncEntity { 

    @PrimaryKey(autoGenerate = true) 
    String taskId; 

    String title; 

    /** Status of the given task. 
    * Enumerated Values: 0 (Active), 1 (Inactive), 2 (Completed) 
    */ 
    @Embedded 
    Status status; 

    @TypeConverters(DateConverter.class) 
    Date startDate; 

    @TypeConverters(StatusConverter.class) 
    public enum Status { 
     ACTIVE(0), 
     INACTIVE(1), 
     COMPLETED(2); 

     private int code; 

     Status(int code) { 
      this.code = code; 
     } 

     public int getCode() { 
      return code; 
     } 
    } 
} 

我的TypeConverter:

public class StatusConverter { 

    @TypeConverter 
    public static Task.Status toStatus(int status) { 
     if (status == ACTIVE.getCode()) { 
      return ACTIVE; 
     } else if (status == INACTIVE.getCode()) { 
      return INACTIVE; 
     } else if (status == COMPLETED.getCode()) { 
      return COMPLETED; 
     } else { 
      throw new IllegalArgumentException("Could not recognize status"); 
     } 
    } 

    @TypeConverter 
    public static Integer toInteger(Task.Status status) { 
     return status.getCode(); 
    } 
} 

当我编译此,我得到一个错误说“错误:(52,12)错误:实体和Pojos必须有一个可用的公共构造函数。你可以有一个空的构造函数或者一个构造函数,它们的参数匹配字段(按名称和类型)。'

更新1 我SyncEntity类:

/** * 为同步所有客房实体基类。 */

@Entity 
public class SyncEntity { 

    @ColumnInfo(name = "created_at") 
    Long createdAt; 

    @ColumnInfo(name = "updated_at") 
    Long updatedAt; 
} 
+0

是否'SyncEntity'定义任何构造函数? – CommonsWare

+0

不,它不。更新了SyncEntity.class的问题。 – Bohsen

+0

我认为你或者需要让你的领域'public',提供'public' setter,或者提供一个'public'构造函数来匹配你的'@ Query'列。否则,Room无法为您提供数据。你唯一的构造函数是零参数。 – CommonsWare

回答

13

我可以在Room使用枚举值与TypeConverters。您的代码中有一些要更改的部分:

1)您必须声明您的实体的字段是公开的,或者必须具有公共的getter/setter。否则你会得到如下错误:

yourField is not public in YourEntity; cannot be accessed from outside package

2)你不需要@Embedded注释为您status领域。它用于嵌套对象。 More from docs.

3)您没有在正确的位置使用@TypeConverters注释。在你的情况下,它可以设置在status字段之上。 More from docs.

4)必须定义一个构造你的实体,否则你会得到如下错误:

Entities and Pojos must have a usable public constructor. You can have an empty constructor or a constructor whose parameters match the fields (by name and type).

您可以定义一个空的构造跳过这个错误。

5)在TypeConverter中使用int而不是Integer。

总和;下面按预期工作:

@Entity(tableName = "tasks") 
public class Task extends SyncEntity { 

    @PrimaryKey(autoGenerate = true) 
    public String taskId; 

    public String title; 

    /** Status of the given task. 
    * Enumerated Values: 0 (Active), 1 (Inactive), 2 (Completed) 
    */ 
    @TypeConverters(StatusConverter.class) 
    public Status status; 

    @TypeConverters(DateConverter.class) 
    public Date startDate; 

    // empty constructor 
    public Task() { 
    } 

    public enum Status { 
     ACTIVE(0), 
     INACTIVE(1), 
     COMPLETED(2); 

     private int code; 

     Status(int code) { 
      this.code = code; 
     } 

     public int getCode() { 
      return code; 
     } 
    } 
} 
+0

感谢@Devrim因为它是“在您的TypeConverter中使用int而不是Integer” –

+0

如果您*必须*为您的枚举使用整数值,则这是正确的方法。切勿使用序号。 –

1

为了帮助简化:

public enum Status { 
    ACTIVE, 
    INACTIVE, 
    COMPLETED; 
} 

那么,你的转换器:

@TypeConverter 
public static Task.Status toStatus(int ordinal) { 
    return Task.Status.values()[ordinal]; 
} 

@TypeConverter 
public static Integer toOrdinal(Task.Status status) { 
    return status.ordinal(); 
} 
+0

作品。所有测试通过。非常感谢。 – Bohsen

+3

普通用户使用起来很危险,它减少了您正在编写的代码数量,但在中间或早期发生的任何更改都可能导致代码中出现奇怪的错误。这不被推荐。 –

+0

@AndrewT那么你会建议恢复和使用原始代码? – Bohsen