Room 不能选择一个构造函数,因为多个构造函数是合适的错误

Posted

技术标签:

【中文标题】Room 不能选择一个构造函数,因为多个构造函数是合适的错误【英文标题】:Room cannot pick a constructor since multiple constructors are suitable error 【发布时间】:2017-11-21 02:17:46 【问题描述】:

我尝试在我的 android kotlin 项目中实现持久库,但在编译时发现此错误:

错误:房间不能选择一个构造函数,因为有多个构造函数 合适的。尝试使用 @Ignore 注释不需要的构造函数。

错误代码:

@Entity
data class Site(
        var name: String = "",
        var url: String = "",
        @PrimaryKey(autoGenerate = true) var id: Long = 0)

【问题讨论】:

【参考方案1】:

我遇到了这个错误,因为 Kotlin 显然为具有默认参数值的单个 Kotlin 构造函数生成了多个 Java 构造函数。工作代码见下:

@Entity
data class Site(
        var name: String,
        var url: String,
        @PrimaryKey(autoGenerate = true) var id: Long)

【讨论】:

我们可以为这个数据类做辅助构造函数吗? 你可以试试伊曼纽尔的回答***.com/a/46526911/3005202【参考方案2】:

上述解决方案都不好,因为它们有效但可能会导致错误。

Kotlin 的Data Class 使用默认构造函数生成多个方法。这意味着equals()、hashCode()、 toString()、componentN() functions 和 copy() 是使用您分配给构造函数的属性生成的。

使用上述解决方案,如

@Entity data class Site(@PrimaryKey(autoGenerate = true) var id: Long) 
    @Ignore constructor() : this(0)
    var name: String = ""
    var url: String = ""
 

仅为 id 生成上面列出的所有方法。使用 equals 会导致不需要的质量,与 toString() 相同。解决这个问题需要你在构造函数中拥有你想要处理的所有属性,并使用 ignore like 添加第二个构造函数

@Entity data class Site(
    @NonNull @PrimaryKey(autoGenerate = true) var id: Long,
    var name: String = "",
    var url: String = "") 
    @Ignore constructor(id = 0, name = ", url = "") : this()
 

你真的应该记住,你通常使用数据类来拥有像 toString 和 copy 这样的方法。只有这个解决方案才能在运行时避免不必要的错误。

【讨论】:

我认为我们也可以使用@JvmOverloads 注解,而不是编写分隔构造函数。 如果您不需要它们,请不要使用 JvmOverloads。生成的代码不会像创建多个构造函数那样高效。【参考方案3】:

这对我有用:

@Entity
data class Site(
    @PrimaryKey(autoGenerate = true) var id: Long = 0),
    var name: String = "",
    var url: String = "",
    @Ignore var ignored: String? = null
)

【讨论】:

重要的是要注意,虽然这有效,但ignored 属性不会添加到数据库中,这可能不是提出问题的人想要做的。 @damia-fuentes 它之所以有效,是因为 Room 处理器知道您在 @Entity 属性之一中使用 @Ignore,因此,它认为您确定需要哪些构造函数。您还可以使用@Ignore private var 使其在您的代码中更加透明。【参考方案4】:

这对我有用

@Entity
data class TaskDetail @Ignore constructor(
    @PrimaryKey(autoGenerate = true)
    var id:Long = 0,
    var taskId:Long = 0,
    var content:String = "")

    constructor():this(id = 0)

我使用@Ignore 来禁止 ROOM 警告

有多个好的构造函数,Room 会选择无参数构造函数。您可以使用@Ignore 注解来消除不需要的构造函数。

并为 ROOM 添加一个默认构造函数。

【讨论】:

【参考方案5】:
@Entity
data class Site @JvmOverloads constructor(
    @ColumnInfo(name = "name") var name: String = "",
    @ColumnInfo(name = "url") var url: String = "",
    @PrimaryKey(autoGenerate = true) var id: Long = 0)

站点的不可变模型类。为了使用 Room 进行编译,我们可以使用 @JvmOverloads 来处理多个构造函数。

【讨论】:

【参考方案6】:

在这里你更改你的应用程序数据库version 并重新启动程序 agian,它会工作:

@Database(entities = arrayOf(Site::class), version = 123) abstract class YourAppDatabase : RoomDatabase() 
    abstract fun yourDao(): YourDao

你也可以试试这个data class:

    @Entity
    data class Site(@PrimaryKey(autoGenerate = true) var id: Long) 
    @Ignore constructor() : this(0)
    var name: String = "",
    var url: String = "",

最后一条指令:您的主键 id 应该手动递增

希望对你有用。 :)

测试表明上述答案无效。

data class TestModel(var id: Int = 0) 
    constructor() : this(0)

    var name: String = "defaultname"
    var testData: String = "defaulttestData"


val testModel = TestModel(5)
testModel.name = "test"

val testModel2 = TestModel(5)
testModel2.testData = "testdata"
testModel2.name = "test"

info  "Test with name set: $testModel" 
info  "Testdata equals Testdata2 $testModel.equals(testModel2)" 

返回带有名称集的测试:TestModel(id=5) 并且 Testdata 等于 Testdata2 true

【讨论】:

请去掉最后一个逗号,,使用@PrimaryKey(autoGenerate = true)这个配置,你总是可以设置id = 0。 :)【参考方案7】:

留下我的答案以防万一。我遇到了同样的问题,上面的答案都没有奏效。唯一有效的是将data class 更改为class。我邀请任何人尝试相同的代码并解释为什么它成功了:

之前

@Entity
data class ImgurGalleryPost (
    @NotNull @PrimaryKey
    var id: String,
    var title: String?,
    var description: String?,
    var datetime: Int?,
    var cover: String?,
    var coverWidth: Int?,
    var coverHeight: Int?,
    var accountUrl: String?,
    var accountId: Int?,
    var privacy: String?,
    var layout: String?,
    var views: Int?,
    var link: String?,
    var ups: Int?,
    var downs: Int?,
    var points: Int?,
    var score: Int?,
    var isAlbum: Boolean?,
    var vote: Boolean?,
    var favorite: Boolean?,
    var nsfw: Boolean?,
    var section: String?,
    var commentCount: Int?,
    var favoriteCount: Int?,
    var topic: String?,
    var topicId: Int?,
    var imagesCount: Int?,
    var inGallery: Boolean?,
    var isAd: Boolean?,
    @NotNull @Ignore
    var tags: List<ImgurGalleryTag>,
    var inMostViral: Boolean?,
    @NotNull @Ignore
    var images: List<ImgurGalleryImage>
)

之后

@Entity
class ImgurGalleryPost (
    @NotNull @PrimaryKey
    var id: String,
    var title: String?,
    var description: String?,
    var datetime: Int?,
    var cover: String?,
    var coverWidth: Int?,
    var coverHeight: Int?,
    var accountUrl: String?,
    var accountId: Int?,
    var privacy: String?,
    var layout: String?,
    var views: Int?,
    var link: String?,
    var ups: Int?,
    var downs: Int?,
    var points: Int?,
    var score: Int?,
    var isAlbum: Boolean?,
    var vote: Boolean?,
    var favorite: Boolean?,
    var nsfw: Boolean?,
    var section: String?,
    var commentCount: Int?,
    var favoriteCount: Int?,
    var topic: String?,
    var topicId: Int?,
    var imagesCount: Int?,
    var inGallery: Boolean?,
    var isAd: Boolean?,
    @NotNull @Ignore
    var tags: List<ImgurGalleryTag>,
    var inMostViral: Boolean?,
    @NotNull @Ignore
    var images: 

List<ImgurGalleryImage>
    )

这真的很奇怪,但我怀疑这是 Android Studio 缓存问题,因为将其更改回 data class 会导致错误再次出现。似乎这是集合字段的某种问题。我检查了生成类中的构造函数,它看起来很好,即使构造函数生成正确,我也不知道为什么构建失败:

public ImgurGalleryPost(@org.jetbrains.annotations.NotNull()
java.lang.String id, @org.jetbrains.annotations.Nullable()
java.lang.String title, @org.jetbrains.annotations.Nullable()
java.lang.String description, @org.jetbrains.annotations.Nullable()
java.lang.Integer datetime, @org.jetbrains.annotations.Nullable()
java.lang.String cover, @org.jetbrains.annotations.Nullable()
java.lang.Integer coverWidth, @org.jetbrains.annotations.Nullable()
java.lang.Integer coverHeight, @org.jetbrains.annotations.Nullable()
java.lang.String accountUrl, @org.jetbrains.annotations.Nullable()
java.lang.Integer accountId, @org.jetbrains.annotations.Nullable()
java.lang.String privacy, @org.jetbrains.annotations.Nullable()
java.lang.String layout, @org.jetbrains.annotations.Nullable()
java.lang.Integer views, @org.jetbrains.annotations.Nullable()
java.lang.String link, @org.jetbrains.annotations.Nullable()
java.lang.Integer ups, @org.jetbrains.annotations.Nullable()
java.lang.Integer downs, @org.jetbrains.annotations.Nullable()
java.lang.Integer points, @org.jetbrains.annotations.Nullable()
java.lang.Integer score, @org.jetbrains.annotations.Nullable()
java.lang.Boolean isAlbum, @org.jetbrains.annotations.Nullable()
java.lang.Boolean vote, @org.jetbrains.annotations.Nullable()
java.lang.Boolean favorite, @org.jetbrains.annotations.Nullable()
java.lang.Boolean nsfw, @org.jetbrains.annotations.Nullable()
java.lang.String section, @org.jetbrains.annotations.Nullable()
java.lang.Integer commentCount, @org.jetbrains.annotations.Nullable()
java.lang.Integer favoriteCount, @org.jetbrains.annotations.Nullable()
java.lang.String topic, @org.jetbrains.annotations.Nullable()
java.lang.Integer topicId, @org.jetbrains.annotations.Nullable()
java.lang.Integer imagesCount, @org.jetbrains.annotations.Nullable()
java.lang.Boolean inGallery, @org.jetbrains.annotations.Nullable()
java.lang.Boolean isAd, @org.jetbrains.annotations.NotNull()
java.util.List<com.kimboo.core.model.ImgurGalleryTag> tags, @org.jetbrains.annotations.Nullable()
java.lang.Boolean inMostViral, @org.jetbrains.annotations.NotNull()
java.util.List<com.kimboo.core.model.ImgurGalleryImage> images) 
    super();

如果有人能找到解决此问题的方法,而无需将 data class 更改为 class,请随时在下方发表评论。

【讨论】:

更多信息:似乎 Room 不会忽略 @Ignore 参数,如果它们在构造函数中 issuetracker.google.com/issues/70762008【参考方案8】:

尝试将变量数据类型从 val 更改为 var :

之前:

 @Entity
    data class Product(
            @PrimaryKey
            val id: String = "",
            val name: String = ""
    )

之后:

@Entity
data class Product(
        @PrimaryKey
        var id: String = "",
        var name: String = ""
)

【讨论】:

【参考方案9】:

错误是由构造函数中初始设置的变量引起的。如果您只有一个构造函数,请将代码更改为此。

@Entity
data class Site(
        val name: String,
        val url: String,
        @PrimaryKey(autoGenerate = true) val id: Long)

如果你也需要空构造函数,那么你应该这样做

@Entity
data class Site() 

  constructor(name: String, url: String): this() 
     this.name = name
     this.url = url
  

    var name: String = "",
    var url: String = "",
    @PrimaryKey(autoGenerate = true) var id: Long = 0

【讨论】:

这也不起作用。给出错误提示 Data class must have at least one primary constructor parameter

以上是关于Room 不能选择一个构造函数,因为多个构造函数是合适的错误的主要内容,如果未能解决你的问题,请参考以下文章

构造函数的特点

多个构造函数的 JavaScript 模式

如果我在 Scala 中定义多个重载构造函数,我不能定义默认值吗?

一个类中可以没有构造器

Dart 多个构造函数

C#面试题整理