2017-06-12 12 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には、使用可能なpublicコンストラクタが必要です。空のコンストラクタ、または(名前と型によって)フィールドに一致するパラメータを持つコンストラクタを持つことができます。

アップデート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'セッターを提供したり、 '@ Query'カラムと一致する' public'コンストラクタを提供する必要があると思います。それ以外の場合は、ルームでデータを提供することはできません。あなたの唯一のコンストラクタはゼロ引数のコンストラクタです。 – CommonsWare

答えて

13

私はTypeConvertersRoomで列挙値を使用することができます。

1)あなたのエンティティのフィールドをパブリックに宣言するか、パブリックゲッター/セッターを持っている必要があります。それとも、エラーの下に取得します:

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

2)あなたはstatusフィールドの@Embedded注釈を必要としません。ネストされたオブジェクト用です。 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でIntegerの代わりにintを使用してください。

合計:期待通りに動作します以下:

@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は、 "Integerの代わりにIntegerをTypeConverterに使用" –

+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元のコードを元に戻して使用することをお勧めしますか? @AndrewT。 – Bohsen

関連する問題