@Ignore和不可变字段的问题

时间:2019-03-26 13:44:48

标签: android kotlin android-room

我的房间有问题。

我在其余的api上使用Gson转换器进行改造,我想和大家分享pojos。通常它可以工作,但是在某些情况下,我需要忽略某些字段,因为我有对象列表。我尝试使用@Ignore批注,但是使用它时,构建过程因以下错误而失败:

  

错误:实体和Pojos必须具有可用的公共构造函数。您   可以有一个空的构造函数或参数匹配的构造函数   字段(按名称和类型)。公共最终班服务{

     

^错误:找不到字段的设置器。       私有最终java.lang.String id = null;

     

^错误:找不到字段的设置器。       私有最终java.lang.String name = null;

     

^错误:找不到字段的设置器。       私有最终java.lang.String description = null;

因此,使用此类,一切正常:

@Entity(tableName = "services")
data class Service(

    @PrimaryKey val id: String,
    val name: String,
    val description: String,
    val parentId: String?
)

由此失败:

@Entity(tableName = "services")
data class Service(

    @PrimaryKey val id: String,
    val name: String,
    val description: String,
    val parentId: String?,
    @Ignore val test: String
)

我正在使用此版本的房间:

implementation 'androidx.room:room-runtime:2.1.0-alpha06'
kapt 'androidx.room:room-compiler:2.1.0-alpha06'

我知道可以使用var而不是val并添加辅助构造函数来解决问题,但是我不想这样做,我更喜欢保留字段的不可变状态。

是忽略注释的错误吗?为什么没有它,一切正常? 任何帮助表示赞赏:)

2 个答案:

答案 0 :(得分:0)

在第二个示例中,服务将转换为Java类,该类具有一个带有四个参数的构造函数。 Room看到@Ignore批注,并且知道它需要绑定3个字段,因此它需要一个具有3个与这些字段类型匹配的参数的构造函数。因为找不到这样的构造函数(或默认的构造函数),所以它失败了。

尝试使最后一个属性为可选,并在构造函数上使用@JvmOverloads批注:

@Entity(tableName = "services")
data class Service @JvmOverloads constructor(
    @PrimaryKey val id: String,
    val name: String,
    val description: String,
    val parentId: String?,
    @Ignore val test: String? = null
)

这将使Kotlin编译器生成3参数构造函数,并使Room再次满意。

  

我正在对其余的api使用Gson转换器进行改造,我想   与房间共享pojos。

您可能应该避免这样做,并使用两组类对API响应和数据库数据进行建模。即使在开始的那一刻,您也需要进行一些“修改”以使所有功能正常运行,如果将来更改API或数据库,则需要在更多位置进行更复杂的更改。

答案 1 :(得分:0)

实际上,您可以使用一个类而不使用@JvmOverloads技巧来保持不变性。您只需要唯一可见的(对Room而言)构造函数即可匹配表的字段。以您的示例为例,

@Entity(tableName = "services")
data class Service @Ignore constructor(
    @PrimaryKey val id: String,
    val name: String,
    val description: String,
    val parentId: String?,
    @Ignore val test: String
) {
    constructor(id: String, name: String, description: String, parentId: String?) : 
        this(id, name, description, parentId, /* some default value for test */)
}