Ich konvertiere ein Projekt in Kotlin und versuche, mein Modell (das auch meine Entität ist) zu einer Datenklasse zu machen, die ich mit Moshi zum Konvertieren der JSON-Antworten von der API verwenden möchte
@Entity(tableName = "movies")
data class MovieKt(
@PrimaryKey
var id : Int,
var title: String,
var overview: String,
var poster_path: String,
var backdrop_path: String,
var release_date: String,
var vote_average: Double,
var isFavorite: Int
)
Ich kann die App wegen des folgenden Fehlers nicht erstellen
Entitäten und Pojos müssen einen verwendbaren öffentlichen Konstruktor haben. Sie können einen leeren Konstruktor oder einen Konstruktor haben, dessen Parameter mit den Feldern übereinstimmen (nach Name und Typ). Setter für Feld kann nicht gefunden werden.
Die Beispiele, die ich gefunden habe, sind nicht weit davon entfernt
Ideen, wie man es löst?
android
kotlin
android-room
android-architecture-components
Leonardo Deleon
quelle
quelle
static
in Kotlin zulässig, aber wenn es kompiliert wird, sieht es so aus, als würden sie es durch einen anderen Namen ersetzen, was dazu führt, dass der Room Annotation-Prozessor nicht in der Lage ist, die Übereinstimmung mit dem Feld herzustellen.Antworten:
Hatte vorher ein ähnliches Problem.
Zuerst habe ich
apply plugin: 'kotlin-kapt'
gradle aktualisiert / hinzugefügt .Als nächstes habe ich es anstelle von
annotationProcessor
Gradle verwendet:kapt "android.arch.persistence.room:compiler:1.0.0-alpha4"
Als letztes musste eine unveränderliche Datenklasse erstellt werden:
@Entity(tableName = "movies") data class MovieKt( @PrimaryKey val id : Int, val title: String, val overview: String, val poster_path: String, val backdrop_path: String, val release_date: String, val vote_average: Double, val isFavorite: Int )
AKTUALISIEREN:
Diese Lösung funktioniert, wenn Sie Klassen für das Modell und Klassen für die Datenbank im selben Android-Modul haben. Wenn Sie Modellklassen im Android Library-Modul und den Rest des Codes in Ihrem Hauptmodul haben, erkennt Room diese NICHT.
quelle
apply plugin: 'kotlin-kapt'
zur Moduldatei hatbuild.gradle
das Problem für mich gelöst, danke!In Ihrem Fall ist dies kein Problem, aber bei anderen kann dieser Fehler auftreten, wenn Sie @Ignore-Parameter in Ihrem primären Konstruktor haben, dh Room erwartet Folgendes:
zum Beispiel:
@Entity(tableName = "movies") data class MovieKt( @PrimaryKey var id : Int, var title: String, @Ignore var overview: String)
wird nicht funktionieren. Dieser Wille:
@Entity(tableName = "movies") data class MovieKt( @PrimaryKey var id : Int, var title: String)
quelle
@Ignore
Felder in Ihrem primären Konstruktor haben. Sie benötigen lediglich einen Konstruktor ohne das Feld, das Room nutzen kann. Siehe meine Antwort für Details.@Ignore
in einem einzelnen Konstruktor ist mit Standardwert und@JvmOverloads
AnmerkungSie müssen einen sekundären Konstruktor wie folgt angeben:
@Entity(tableName = "movies") data class MovieKt( @PrimaryKey var id : Int, var title: String, var overview: String, var poster_path: String, var backdrop_path: String, var release_date: String, var vote_average: Double, var isFavorite: Int ) { constructor() : this(0, "", "", "", "", "", 0.0, 0) }
quelle
Was hat bei mir funktioniert:
@Entity(tableName = "movies") data class MovieKt( @PrimaryKey var id : Int? = 0, var title: String? = "", var overview: String? = "", var poster_path: String? = "", var backdrop_path: String? = "", var release_date: String? = "", var vote_average: Double? = 0.0, var isFavorite: Int? = 0 )
quelle
Für mich war alles, was ich tun musste, der Datenklasse einen Konstruktor hinzuzufügen, an den leere Parameter wie folgt gesendet wurden:
@Entity(tableName = "posts") data class JobPost( @Ignore @SerializedName("companyLogo") var companyLogo: String, @Ignore @SerializedName("companyName") var companyName: String, @Ignore @SerializedName("isAggregated") var isAggregated: String, @PrimaryKey(autoGenerate = false) @SerializedName("jobID") var jobID: String, @Ignore @SerializedName("jobTitle") var jobTitle: String, @Ignore @SerializedName("postedOn") var postedOn: String, @Ignore @SerializedName("region") var region: String ) { constructor() : this("","","","","","","") }
quelle
e.g: var postedOn: String = "" // this should fix the error as well
Um die Antworten von @evanchooly und @daneejela zu erweitern, benötigen Sie einen sekundären Konstruktor, um
@Ignore
Parameter in Ihrem primären Konstruktor verwenden zu können. Dies ist so, dass Room immer noch einen Konstruktor hat, den er zum Instanziieren Ihres Objekts verwenden kann. Wenn wir in Ihrem Beispiel eines der Felder ignorieren:@Entity(tableName = "movies") data class MovieKt( @PrimaryKey var id : Int, var title: String, var overview: String, var poster_path: String, var backdrop_path: String, @Ignore var release_date: String, @Ignore var vote_average: Double, @Ignore var isFavorite: Int ) { constructor(id: Int, title: String, overview: String, poster_path: String, backdrop_path: String) { this(id, title, overview, poster_path, backdrop_path, "", 0.0, 0) } }
quelle
constructor(params) : this(params from primary constructor) { }
Ich hatte das gleiche Problem. Sie können die @ Ignore-Felder in den Klassenkörper verschieben. Zum Beispiel :
@Entity(tableName = "movies") data class MovieKt( @PrimaryKey var id : Int, var title: String ){ //here @Ignore var overview: String }
quelle
Kotlin erlaubt einen langen Parameternamen, dies funktioniert jedoch nicht, wenn der Raum Java-Code generiert.
quelle
Ich denke, dass eine gute Option zur Lösung ist:
@Entity(tableName = "movies") data class MovieKt( @PrimaryKey var id : Int = 0, var title: String = "", var overview: String = "", var poster_path: String = "", var backdrop_path: String = "", var release_date: String = "", var vote_average: Double = 0.0, var isFavorite: Int = 0 )
quelle
Ich hatte auch dieses Problem, aber ich erkannte, dass das Problem darin bestand, dass ich die Annotation @Embedded zu einer Eigenschaft hinzufügte, die bereits einen Typkonverter hatte. Daher sollte jeder, der das gleiche Problem hat, die Eigenschaftsdeklarationen für Ihre Modellklasse sorgfältig prüfen und sicherstellen, dass das @ Eingebettete Anmerkungen befinden sich nicht in einer Eigenschaft, der ein Typkonverter zugeordnet ist.
quelle
Ich hatte dieses Problem mit einer Entität (alle Felder wurden ordnungsgemäß initialisiert,
var
wie viele der Antworten hier vorschlagen), die eine Liste verwandter, nicht primitiver Elemente wie das OP in dieser SO-Frage enthielt . Zum Beispiel:@Entity(tableName = "fruits") data class CachedFruitEntity( @PrimaryKey var id: Long = 0L, @Embedded(prefix = "buyer_") var buyerEntity: CachedBuyerEntity? = null @TypeConverters(VendorsConverter::class) var vendorEntities: List<CachedVendorEntity?> = listOf()))
Das heißt, es hat ein eingebettetes Feld, und es dauerte eine Weile, bis mir klar wurde, dass ich stattdessen einen Typkonverter für die Lieferantenentitätsliste benötigte (der Compiler warf nicht das Übliche aus.
Error:(58, 31) error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.
Daher war meine Lösung dieser Antwort sehr ähnlichDieser Github-Thread für Google-Architekturkomponenten enthält weitere Informationen zu diesem irreführenden Fehler, ist sich jedoch nicht sicher, ob das Problem bereits behoben wurde.
quelle
Wie in den Room-Dokumenten angegeben, müssen Sie einen leeren öffentlichen Konstruktor erstellen . Wenn Sie andere benutzerdefinierte Konstruktoren deklarieren möchten, müssen Sie gleichzeitig eine
@Ignore
Anmerkung hinzufügen .@Entity public class CartItem { @PrimaryKey public int product_id; public int qty; public CartItem() { } @Ignore public CartItem(int product_id, int count) { this.product_id = product_id; this.qty = count; } }
quelle
Heute hatte ich dieses Problem. Ich habe verwendet
@Ignore
, deshalb habe ich den Fehler bekommen. Um dies zu lösen, habe ich einen sekundären Konstruktor erstellt. Mein Code sieht also ungefähr so aus:@Entity(tableName = "profile") data class Profile( @field:SerializedName("id") @PrimaryKey @ColumnInfo(name = "id") var id:Long, @field:SerializedName("foo") @ColumnInfo(name = "foo") var foo:String?, @field:SerializedName("bar") @Ignore var Bar:String? ){ constructor(id:Long, foo:String) : this(id, foo, null) }
Das hat bei mir funktioniert.
quelle
Es stellte sich heraus, dass es sich um einen Fehler in der Bibliothek https://github.com/googlesamples/android-architecture-components/issues/49 handelte
quelle
https://issuetracker.google.com/issues/62851733
Ich fand, dass dies der Projektionsfehler von @ Relation ist ! kein Kotlin Sprachproblem. basierend auf Google GithubBrowserSample Java ist auch ein Fehler aufgetreten, aber eine andere Fehlermeldung.
Unten ist mein Kotlin-Code:
data class UserWithCommunities( @Embedded var user: User = User(0, null), @Relation(parentColumn = "id", entityColumn = "users_id", entity = CommunityUsers::class, projection = arrayOf("communities_id")) // delete this line. var communityIds: List<Int> = emptyList() )
richtig:
data class UserWithCommunities( @Embedded var user: User = User(0, null), @Relation(parentColumn = "id", entityColumn = "users_id", entity = CommunityUsers::class) var communityList: List<CommunityUsers> = emptyList() )
quelle
Gleicher Fehler, viel seltsamere Lösung: Geben Sie den Cursor nicht mit reactivex
Maybe<Cursor>
auf Ihrem Dao zurück.Flowable
,Single
UndObservable
arbeiten entweder nicht.Beißen Sie einfach in die Kugel und tätigen Sie den reaktiven Anruf außerhalb der Dao-Anfrage. Vor:
@Dao interface MyDao{ @Query("SELECT * FROM mydao") fun getCursorAll(): Flowable<Cursor> }
Nach:
@Dao interface MyDao{ @Query("SELECT * FROM mydao") fun getCursorAll(): Cursor }
Meta:
Android Studio 3.2 Build #AI-181.5540.7.32.5014246, built on September 17, 2018 JRE: 1.8.0_152-release-1136-b06 x86_64 JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o macOS 10.12.6
quelle
Fügen Sie einfach die folgende Anmerkung zu jedem Konstruktor hinzu, der die Fehler verursacht, und fügen Sie einen neuen leeren Konstruktor hinzu.
quelle
Verwenden Sie nicht die Datenklasse, sondern die normale Klasse. Diese Methode wird das Problem lösen
quelle
Mit 2.1.0-alpha6 stellte sich heraus, dass es sich in Dao um einen ungültigen Rückgabetyp handelt. Das erwartete Korrigieren des Rückgabetyps wurde behoben.
quelle
Für mich habe ich 'lat' & 'long' als Variablennamen in der Datenklasse (Entity) für Kotlin verwendet, sodass es in Breiten- und Längengrad umbenannt wurde.
Funktioniert nicht:
@Entity(tableName = "table_User") data class User(@PrimaryKey var userId : Int, @ColumnInfo(name = "first_name") var firstName: String , @ColumnInfo(name = "last_name") var lastName: String , @ColumnInfo(name = "password") var password: String , @ColumnInfo(name = "dob") var dob: Long , @ColumnInfo(name = "address") var address: String , @ColumnInfo(name = "lat") var latitude: Double , @ColumnInfo(name = "long") var longitude: Double) { }
Arbeiten:
@Entity(tableName = "table_User") data class User(@PrimaryKey var userId : Int, @ColumnInfo(name = "first_name") var firstName: String , @ColumnInfo(name = "last_name") var lastName: String , @ColumnInfo(name = "password") var password: String , @ColumnInfo(name = "dob") var dob: Long , @ColumnInfo(name = "address") var address: String , @ColumnInfo(name = "latitude") var latitude: Double , @ColumnInfo(name = "longitude") var longitude: Double) { }
quelle
Das Kotlin-Plugin erkennt keine AnnotationProcessor-Abhängigkeiten. Verwenden Sie also die neueste Version des Kotlin-Annotation-Prozessors. Fügen Sie diese Zeile oben in die
build.gradle
Datei auf Modulebene einapply plugin: 'kotlin-kapt'
mögen
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' // add this line android { compileSdkVersion 28 defaultConfig { ........ } }
Vergessen Sie nicht, die compileSdkVersion entsprechend zu ändern.
quelle
Wie in der Raumdatenbank angegeben
Entity
:Wenn Sie also einen leeren Konstruktor hinzufügen und Ihren parametrisierten Konstruktor mit Anmerkungen versehen,
@Ignore
wird Ihr Problem gelöst. Ein Beispiel:public class POJO { long id; String firstName; @Ignore String lastName; public POJO() { } @Ignore public POJO(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } // getters and setters // ... }
quelle
In meinem Fall habe ich in einer der Dao-Abfragen keinen Tipp zurückgegeben. Ich hoffe, es hilft anderen. Danke
quelle
Für eine Variation der FutureShocked-Antwort, die autoGenerate implementiert:
@Entity(tableName = "movies") data class MovieKt( var title: String, var overview: String, var poster_path: String, var backdrop_path: String, @Ignore var release_date: String, @Ignore var vote_average: Double, @Ignore var isFavorite: Int ) { @PrimaryKey(autoGenerate = true) var id : Int = 0 constructor(title: String, overview: String, poster_path: String, backdrop_path: String) { this(id, title, overview, poster_path, backdrop_path, "", 0.0, 0) } }
quelle