Search code examples
androidandroid-roomandroid-architecture-components

Android Architecture Components: Using Enums


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;
}

Solution

  • 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;
            }
        }
    }