【问题标题】:Room: related entities - usable public constructorRoom:相关实体 - 可用的公共构造函数
【发布时间】:2017-10-26 13:47:30
【问题描述】:

为了获得与 Room 的 OneToMany 关系,我创建了一个带有 @Embedded 对象和 @Relation 变量的 POJO。

data class SubjectView(
    @Embedded
    var subject: Subject,

    @Relation(parentColumn = "idWeb", entityColumn = "subject_id", entity = Topic::class)
    var topics: List<Topic>?
)

但是在编译时出现这个错误

 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)
[...]
Tried the following constructors but they failed to match:
SubjectView(biz.eventually.atpl.data.db.Subject,java.util.List<biz.eventually.atpl.data.db.Topic>) : [subject : subject, topics : null]

嗯,构造函数 [subject : subject, topics : null] 看起来不错???

但是,如果我使用无参数构造函数和全参数构造函数更改我的类,它确实有效。

class SubjectView() {
    @Embedded
    var subject: Subject = Subject(-1, -1, "")

    @Relation(parentColumn = "idWeb", entityColumn = "subject_id", entity = Topic::class)
    var topics: List<Topic>? = null

    constructor(subject: Subject, topics: List<Topic>?) : this() {
        this.subject = subject
        this.topics = topics
    }
}

我想知道为什么第一个(更快的)版本无法编译,因为它不像文档显示的那样。

构造函数(数据)类中所有变量的默认参数(正如我在其他帖子中看到的那样)似乎不是强制性的?

谢谢

【问题讨论】:

    标签: android kotlin entities android-room android-architecture-components


    【解决方案1】:

    数据类如何生成构造函数有几个主题。

    由于您的构造函数中有一个可为空的对象,它将生成所有可能的构造函数。这意味着它会生成

    constructor(var subject: Subject)
    constructor(var subject: Subject, var topics: List<Topic>) 
    

    有两种方法可以解决这个问题。第一个是预定义所有值,并使用所需的构造函数创建另一个忽略的构造函数。

    data class SubjectView(
        @Embedded
        var subject: Subject,
    
        @Relation(parentColumn = "idWeb", entityColumn = "subject_id", entity = Topic::class)
        var topics: List<Topic> = ArrayList()
    ) {
     @Ignore constructor(var subject: Subject) : this(subject, ArrayList())
    }
    

    另一种方法是创建一个半填充的数据类,例如

    data class SubjectView(@Embedded var subject: Subject) {
        @Relation var topics: List<Topic> = ArrayList()
    }
    

    注意第一个解决方案是正确的解决方案,您需要将@Ignore 设置为任何其他构造函数。

    【讨论】:

    • 嗨!我不明白您的回答,因为您将topics 设为非空。或者我们希望 topics 可以为空......
    • 即使你想为空,你也应该创建一个 Topic 实例并验证条目是否为“空”,而不是空。
    • 或者像data class SubjectView @JvmOverloads constructor(...)一样在主类构造函数中添加@JvmOverloads注解
    • 初学者犯的第一个错误..使用jvmoverloads。如果您不需要它们,请尽量避免它们。使用 JvmOverloads 不好的原因有很多。 (编译时间、速度、生成的代码……)
    • 我对你最初的陈述有点困惑。据我了解,只有在使用 default 参数时才会生成多个构造函数,而不仅仅是在使用可为空参数时。
    猜你喜欢
    • 2017-11-20
    • 2019-05-21
    • 2020-09-03
    • 1970-01-01
    • 2020-10-31
    • 1970-01-01
    • 2018-10-19
    • 2011-02-14
    • 1970-01-01
    相关资源
    最近更新 更多