Is it possible to use an Enum type as an embedded field in an Entity class with the new Android Architecture Components and Room Persistence Library?
My Entity (with embedded Enum):
@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;
}
}
}
My 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();
}
}
When I compile this I get an error saying Error:(52, 12) error: 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).
Update 1 My SyncEntity class:
/**
* Base class for all Room entities that are synchronized.
*/
@Entity
public class SyncEntity {
@ColumnInfo(name = "created_at")
Long createdAt;
@ColumnInfo(name = "updated_at")
Long updatedAt;
}
I can use enum values at Room
with TypeConverters
. There are some parts to change at your code:
1) You must declare your Entity's fields public or they must have public getters/setters. Or you'll get below error:
yourField is not public in YourEntity; cannot be accessed from outside package
2) You don't need the @Embedded
annotation for your status
field. It is for nested objects. More from docs.
3) You didn't use the @TypeConverters
annotation at the correct place. In your case it can be set above the status
field. More from docs.
4) You must define a constructor for your Entity or you'll get below error:
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).
You can define an empty constructor to skip this error.
5) Use int instead of Integer in your TypeConverter.
Sum; below works as expected:
@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;
}
}
}