Android架构组件:使用枚举

Boh*_*sen 28 android android-room android-architecture-components

是否可以使用新的Android架构组件和房间持久性库将Enum类型用作Entity类中的嵌入字段?

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

@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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的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();
    }
}
Run Code Online (Sandbox Code Playgroud)

当我编译这个时,我得到一个错误,说'错误:(52,12)错误:实体和Pojos必须有一个可用的公共构造函数.您可以拥有一个空构造函数或构造函数,其参数与字段匹配(按名称和类型).

更新1 我的SyncEntity类:

/***同步的所有Room实体的基类.*/

/**
 * 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;
}
Run Code Online (Sandbox Code Playgroud)

Dev*_*rim 42

我可以用枚举值RoomTypeConverters.您的代码中有一些要更改的部分:

1)您必须公开您的实体的字段,或者他们必须有公共的getter/setter.或者你会得到以下错误:

yourFieldYourEntity中不公开; 无法从外部包裹访问

2)您不需要@Embedded为您的status字段添加注释.它适用于嵌套对象.更多来自文档.

3)您没有@TypeConverters在正确的位置使用注释.在您的情况下,它可以设置在status字段上方.更多来自文档.

4)您必须为您的实体定义构造函数,否则您将得到以下错误:

实体和Pojos必须具有可用的公共构造函数.您可以拥有一个空构造函数或其参数与字段匹配的构造函数(按名称和类型).

您可以定义一个空构造函数来跳过此错误.

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 您不应该使用序数的原因是您可以选择重新排列枚举的顺序(例如,如果添加一个新的枚举)-因此,当其从数据库中拉出时,您可能会将其映射到错误的值。您最好使用String。@CheokYanCheng (2认同)

小智 8

我遇到了类似的问题。Devrim对这个问题的回答很有帮助。但是我的实体有一个可为空的对象。

在这种情况下,插入操作将返回错误。这是由枚举类型中的原始“代码”成员引起的。

我开发了以下实现来解决此错误。

首先,我将枚举类型固定如下。

package com.example.models.entities.enums;


import androidx.room.TypeConverter;

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

    private final Integer code;

    Status(Integer value) {
        this.code = value;
    }
    public Integer getCode() {
        return code;
    }

    @TypeConverter
    public static Status getStatus(Integer numeral){
        for(Status ds : values()){
            if(ds.code == numeral){
                return ds;
            }
        }
        return null;
    }

    @TypeConverter
    public static Integer getStatusInt(Status status){

        if(status != null)
            return status.code;

        return  null;
    }

}
Run Code Online (Sandbox Code Playgroud)

然后,我按如下所示更新实体。

package com.example.models.entities;


import com.example.models.TypeConverters.DateConverter;
import com.example.models.entities.enums.Status;

import java.util.Date;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import androidx.room.TypeConverters;

@Entity(tableName = "tasks")
@TypeConverters({Status.class, DateConverter.class})

public class Task extends SyncEntity {

    @PrimaryKey(autoGenerate = true)
    String taskId;

    @NonNull
    String title;

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

    @NonNull
    Date startDate;


    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    @NonNull
    public String getTitle() {
        return title;
    }

    public void setTitle(@NonNull String title) {
        this.title = title;
    }

    @Nullable
    public Status getStatus() {
        return status;
    }

    public void setStatus(@Nullable Status status) {
        this.status = status;
    }

    @NonNull
    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(@NonNull Date startDate) {
        this.startDate = startDate;
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,我可以在Room数据库中管理可为空的枚举属性。

我希望我能够在类似情况下提供帮助。

快乐的编码。