web-dev-qa-db-fra.com

Room ne peut pas choisir un constructeur, car plusieurs constructeurs conviennent. Error

J'essaie d'implémenter une bibliothèque persistante dans mon projet kotlin Android, mais je détecte cette erreur lors de la compilation:

erreur: Room ne peut pas choisir un constructeur car plusieurs constructeurs sont adapté. Essayez d'annoter les constructeurs indésirables avec @Ignore.

Code d'erreur:

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

J'ai eu cette erreur parce que Kotlin génère apparemment plusieurs constructeurs Java pour un seul constructeur Kotlin avec des valeurs d'argument par défaut. Code de travail voir suivant:

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

Aucune des solutions ci-dessus n'est bonne, car elles fonctionnent mais peuvent provoquer des erreurs.

La classe Data de Kotlin génère plusieurs méthodes à l'aide du constructeur par défaut. Cela signifie que equals () , hashCode () , toString () , composantN () (fonctions) et copy () sont générés à l'aide du attributs que vous attribuez à votre constructeur.

En utilisant les solutions ci-dessus comme 

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

génère toutes les méthodes énumérées ci-dessus uniquement pour id. L'utilisation de l'égal conduit à une qualité indésirable, identique à toString (). Pour résoudre ce problème, vous devez avoir tous les attributs que vous souhaitez traiter dans le constructeur et ajouter un second constructeur en utilisant ignore comme

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

N'oubliez pas que vous utilisez généralement des classes de données pour utiliser des méthodes telles que toString et copy. Seule cette solution permet d'éviter les bogues indésirables lors de l'exécution.

6
Emanuel S

Cela a fonctionné pour moi:

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

ça marche pour moi

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

J'utilise @ Ignore pour interdire l'avertissement ROOM

Il y a plusieurs bons constructeurs et Room choisira le constructeur sans argument. Vous pouvez utiliser l'annotation @Ignore pour éliminer les constructeurs indésirables.

Et ajoutez un constructeur par défaut pour ROOM.

1
Zebulon Li

Ici, vous changez votre base de données d'applications version et redémarrez le programme une fois, cela fonctionnera:

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

et vous pouvez aussi essayer ceci data class:

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

et la dernière instruction: votre clé primaire id devrait être incrémentée manuellement .

J'espère que cela fonctionne pour vous. :)

Testez pour montrer que les réponses ci-dessus ne sont pas valides.

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)}" }

renvoie Test avec le nom défini: TestModel (id = 5) et Testdata est égal à Testdata2 true

0
SpkingR

Essayez de changer le type de données variable de val en var:

AVANT :  

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

APRÈS :  

@Entity
data class Product(
        @PrimaryKey
        var id: String = "",
        var name: String = ""
)
0
m.fahad butt

Je laisse juste ma réponse au cas où cela aiderait quelqu'un. J'ai rencontré le même problème, aucune des réponses ci-dessus n'a fonctionné. La seule chose qui a fonctionné a été de passer d'un data class à un class. J'invite n'importe qui à essayer le même code et à expliquer pourquoi il a fait l'affaire:

Avant

@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>
)

Après

@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>
    )

C’est vraiment bizarre, mais je doute que ce soit un problème de cache d’Android Studio, car le fait de revenir au data class entraîne la réapparition de l’erreur. Cela semble être un problème avec les champs de collection. J'ai vérifié le constructeur dans la classe générée et ça avait l'air bien, je ne sais pas pourquoi la construction échouait alors même que le constructeur était généré correctement:

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

Si quelqu'un peut trouver un moyen de résoudre ce problème sans passer de data class à class, n'hésitez pas à commenter ci-dessous.

0
4gus71n

L'erreur est provoquée par les variables initialement définies dans le constructeur. Si vous n'avez qu'un seul constructeur, remplacez votre code par ceci.

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

Si vous avez aussi besoin d'un constructeur vide, alors vous devriez faire comme ceci

@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
}
0
Rafael