Почему приложение Android с Jetpack Compose, Room и Dagger-Hilt дает сбой?

Я делаю приложение для Android с помощью Jetpack Compose, Room и Dagger-Hilt.
Приложение вылетает со следующим исключением:

java.lang.RuntimeException: Cannot find implementation for com.pbpu.android.data.local.source.Database. Database_Impl does not exist

Уровень проекта build.gradle.kts:

plugins {
    id("com.android.application") version "8.1.0" apply false
    id("org.jetbrains.kotlin.android") version "1.8.10" apply false
    id("com.google.devtools.ksp") version "1.8.10-1.0.9" apply false
    id("com.google.dagger.hilt.android") version "2.47" apply false
}

Используемые зависимости:

//    DI
    implementation("com.google.dagger:hilt-android:2.47")
    ksp("com.google.dagger:hilt-compiler:2.47")
    implementation("androidx.hilt:hilt-navigation-compose:1.0.0")
//    Room
    implementation("androidx.room:room-ktx:2.5.2")
    implementation("androidx.room:room-runtime:2.5.2")
    ksp("androidx.room:room-compiler:2.5.2")
//    Other dependencies

Если я изменю зависимости на:

//    DI
    implementation("com.google.dagger:hilt-android:2.47")
    ksp("com.google.dagger:hilt-compiler:2.47")
    implementation("androidx.hilt:hilt-navigation-compose:1.0.0")
//    Room
    implementation("androidx.room:room-ktx:2.5.2")
    implementation("androidx.room:room-runtime:2.5.2")
    kapt("androidx.room:room-compiler:2.5.2")
//    Other dependencies

Затем компиляция завершается с ошибкой с сообщением:

path\to\file\RecordWithMarkingsDao.java:17: error: Type of the parameter must be a class annotated with @Entity or a collection/array of it.
    com.pbpu.android.domain.model.RecordWithMarkings entity, @org.jetbrains.annotations.NotNull
                                                     ^

Но тот же код компилируется, если я использую ksp("androidx.room:room-compiler:2.5.2") или даже annotationProcessor("androidx.room:room-compiler:2.5.2"), но затем приложение вылетает с исключением, как указано ранее!

Record.kt

@Entity(tableName = "records")
data class Record(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(index = true)
    var idRecord: Long = 0,
//    Other fields
)

Marking.kt

@Entity(
    tableName = "markings",
    foreignKeys = [
        ForeignKey(
            entity = Record::class,
            parentColumns = ["idRecord"],
            childColumns = ["fkIdRecord"],
            onDelete = ForeignKey.CASCADE,
            onUpdate = ForeignKey.CASCADE,
        ),
    ],
)
data class Marking(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(index = true)
    var idMarking: Long = 0,
    @ColumnInfo(index = true)
    val fkIdRecord: Long = 0,
//    Other fields
)

RecordWithMarkings.kt

data class RecordWithMarkings(
    @Embedded
    val record: Record,
    @Relation(
        parentColumn = "idRecord",
        entityColumn = "fkIdRecord",
    )
    val markings: List<Marking>,
)

Как решить эту проблему?

Мы будем признательны за любую помощь и при необходимости запросим любую дополнительную информацию.

Спасибо.

я думаю, вы не добавили аннотацию @Entity к классу данных, который вы используете как таблицу в базе данных

Chirag Thummar 12.08.2023 06:31

Нет, на самом деле это средний класс, который включает @Embedded и @Relation и не нуждается в аннотации @Entity (по крайней мере, это то, что я видел во многих онлайн-уроках). Я добавил код для этих классов в вопрос.

dev.tejasb 12.08.2023 08:15

Тем не менее, я попытался добавить @Entity в класс в RecordWithMarkings.kt, но выдает ошибку: error: Entities cannot have relations.

dev.tejasb 12.08.2023 08:24
0
3
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Похоже, проблема в DAO, проверьте правильность:

  • У RecordWithMarkingsDao.java должны быть методы, связанные с получением RecordWithMarkings объектов. Эти методы должны возвращать RecordWithMarkings или список RecordWithMarkings, но не должны принимать RecordWithMarkings в качестве аргумента. Вот пример того, как может выглядеть DAO:
@Dao
interface RecordWithMarkingsDao {

    @Transaction
    @Query("SELECT * FROM records")
    fun getAllRecordsWithMarkings(): List<RecordWithMarkings>

    @Transaction
    @Query("SELECT * FROM records WHERE idRecord = :recordId")
    fun getRecordWithMarkings(recordId: Long): RecordWithMarkings
}
  • для операций CRUD используйте отдельные DAO (или методы внутри одного DAO), которые работают напрямую с сущностями Record и Marking, например:
@Dao
interface RecordDao {

    @Insert
    fun insertRecord(record: Record): Long

    @Update
    fun updateRecord(record: Record)

    @Delete
    fun deleteRecord(record: Record)
}

@Dao
interface MarkingDao {

    @Insert
    fun insertMarking(marking: Marking): Long

    @Update
    fun updateMarking(marking: Marking)

    @Delete
    fun deleteMarking(marking: Marking)
}

Это должно помочь :)

Да, кажется, я упустил из виду официальное руководство, которое не включало методы вставки или обновления в DAO среднего класса, а только функции чтения.

dev.tejasb 12.08.2023 17:56

Другие вопросы по теме