私はAndroid kotlinプロジェクトに永続ライブラリを実装しようとしますが、コンパイル時にこのエラーをキャッチします。
エラー:複数のコンストラクターが適しているため、部屋はコンストラクターを選択できません。 @Ignoreを使用して、不要なコンストラクタに注釈を付けてください。
エラーコード:
@Entity
data class Site(
var name: String = "",
var url: String = "",
@PrimaryKey(autoGenerate = true) var id: Long = 0)
Kotlinは明らかに、デフォルトの引数値を持つ単一のKotlinコンストラクターに対して複数のJavaコンストラクターを生成します。作業コードは次を参照してください。
@Entity
data class Site(
var name: String,
var url: String,
@PrimaryKey(autoGenerate = true) var id: Long)
上記の解決策はどれもうまくいきませんが、エラーを引き起こす可能性があります。
Kotlinの Data Class は、デフォルトのコンストラクターを使用していくつかのメソッドを生成します。つまり、 equals() 、 hashCode() 、 toString() 、 componentN()関数 および- 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を使用して2番目のコンストラクタを追加する必要があります。
@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などのメソッドを作成することに注意してください。このソリューションのみが、実行中の不要なバグを回避するために機能しています。
これは私のために働いた:
@Entity
data class Site(
@PrimaryKey(autoGenerate = true) var id: Long = 0),
var name: String = "",
var url: String = "",
@Ignore var ignored: String? = null
)
@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を使用して複数のコンストラクターを処理できます。
変数のデータ型をvalからvarに変更してみてください。
前:
@Entity
data class Product(
@PrimaryKey
val id: String = "",
val name: String = ""
)
AFTER:
@Entity
data class Product(
@PrimaryKey
var id: String = "",
var name: String = ""
)
これは私のために働く
@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のデフォルトコンストラクターを追加します。
ここで、アプリデータベース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
エラーは、コンストラクターで変数を最初に設定したことが原因です。コンストラクターが1つしかない場合は、コードをこれに変更します。
@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
}