2017-06-12 127 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