Проблема с внедрением DAO - RoomDatabase не найдена с Hilt Android

Итак, я пытаюсь использовать Room в личном проекте. Я реализовал свои объекты, dao и расширенный класс приложения roomdatabase:

@Database(
version = 1,
entities = [
    UserDBEntity::class
]
)
abstract class MyDatabase: RoomDatabase() {

    companion object {
        const val DATABASE_NAME = "MyDb"
    }

    abstract fun getUserDao(): UserDao
}

Однако я также пытаюсь использовать с ним Hilt DI, поэтому я создал такой модуль:

@InstallIn(ApplicationComponent::class)
@Module
object PersistenceModule {

    lateinit var database: MyDatabase

    @Provides
    @Singleton
    fun provideDatabase(@ApplicationContext context: Context): MyDatabase{
        database =  Room.databaseBuilder(
            context,
            MyDatabase::class.java,
            MyDatabase.DATABASE_NAME
        )
            .fallbackToDestructiveMigration()
            .build()

        return database
    }

    @Provides
    @Singleton
    fun provideUserDao(db: MyDatabase): UserDao {
        return db.getUserDao()
    }
}

Мне все кажется хорошо. Однако, когда я пытаюсь скомпилировать, у меня появляется следующее сообщение об ошибке:

файл класса для androidx.room.RoomDatabase не найден

Есть идеи, что я пропустил?

Если это может вам помочь, я попытался изменить свой build.gradle следующим образом:

реализация androidx.room:room-runtime:2.3.0-alpha02

К этому :

api androidx.room:room-runtime:2.3.0-alpha02

И при этом он успешно компилируется, но я не думаю, что это хорошая практика, просматривая учебные пособия, которые я нашел.

Не сомневайтесь, если вам понадобится дополнительная информация о моем коде.

Спасибо за ответ :)

РЕДАКТИРОВАТЬ:

Мой build.gradle для комнаты:

implementation "androidx.room:room-runtime:2.3.0-alpha02"
kapt "androidx.room:room-compiler:2.3.0-alpha02"
implementation "android.arch.persistence.room:runtime:1.1.1"
kapt "android.arch.persistence.room:compiler:1.1.1"

При этом также:

apply plugin: 'kotlin-kapt'

ИЗМЕНИТЬ 2:

Думаю, я нашел причину проблемы. Я вызвал свой метод DAO в таком классе:

@Singleton
class DBManagerImpl @Inject constructor(
    private val userDao: UserDao
) : DBManager {

    override fun insertUser(userDBEntity: UserDBEntity) {
       userDao.insertUser(userDBEntity)
    }
}

Кажется, проблема в причине инъекции userDao, если я прокомментирую частную строку val userDao: UserDao, у меня больше нет ошибки. Поэтому я думаю, что моя проблема связана с тем, что я ввожу объект dao.


person Boysteuf    schedule 24.08.2020    source источник


Ответы (7)


Я столкнулся с этой проблемой, потому что добавлял зависимости места в основной модуль, поэтому для тех, кто использует модульную архитектуру, убедитесь, что вы добавили зависимости места в модуль приложения.

person Mostafa Anter    schedule 17.03.2021

Поскольку вы не указали, как вы создали свой объект dao, я написал свой собственный и предоставил его в этом ответе. Это должно работать:

Класс базы данных

@Database(version = 1,entities = [UserDBEntity::class])
abstract class MyDataBase() : RoomDatabase() {
    
   abstract fun myDao(): UserDao

   companion object {
      val DATABASE_NAME = "my_db"
   }
}

DAO

@Dao
inteface UserDao {
   // your functions
   @Query("SELECT * FROM UserDBEntity")
   suspend fun get(): List<User>

   @Insert(onConflict = OnConflictStrategy.REPLACE)
   suspend fun insert(entity: UserDBEntity)
}

Модуль помещения

@InstallIn(ApplicationComponent::class)
@Module
object RoomModule {
   @Singleton
   @Provides
   fun provideMyDB(@ApplicationContext context: Context): MyDataBase {
       return Room.databaseBuilder(context, 
               MyDataBase::class.java,
               MyDataBase.DATABASE_NAME
         ).fallbackToDestructiveMigration().build()
   }
}

@Singleton
@Provides
fun provideMyDao(myDB: MyDataBase): UserDao {
    return myDB.myDao()
}
person Andrew    schedule 05.09.2020

У меня такая же проблема. Его можно исправить с помощью Dagger, но не с помощью Hilt. По крайней мере на данный момент. Похоже, что на данный момент лучшее решение - использовать api вместо implementation. Если вы сильно хотите этого избежать, вы можете использовать что-то вроде этого:

@InstallIn(ApplicationComponent::class)
@Module
object PersistenceModule {

    lateinit var database: MyDatabase
    
    private fun getDatabase(context: Context): MyDatabase {
            if (!::database.isInitialized) {
                database = Room.databaseBuilder(
                    context,
                    MyDatabase::class.java,
                    MyDatabase.DATABASE_NAME
                )
                    .fallbackToDestructiveMigration()
                    .build()
            }
            return database
        
    }

    @Provides
    @Singleton
    fun provideUserDao(@ApplicationContext context: Context): UserDao {
        return getDatabase(context).getUserDao()
    }
}

Но, как я уже сказал - может быть, пока лучше оставить api в градиенте

person Andrey Turkovsky    schedule 09.02.2021

Попробуйте api androidx.room:room-runtime:2.3.0-alpha02 вместо реализации androidx.room:room-runtime:2.3.0-alpha02. Не знаю почему, но у меня это сработало

person Denis Zozulinsky    schedule 02.05.2021

У вас есть 2 строки в файле приложения gradle:

apply plugin: 'kotlin-kapt'

kapt "androidx.room:room-compiler:2.2.5"
person Petrus Nguyễn Thái Học    schedule 24.08.2020
comment
Да, у меня есть это в моем build.gradle (добавлено в мой вопрос выше): apply plugin: 'kotlin-kapt' implementation androidx.room:room-runtime:2.3.0-alpha02 kapt androidx.room:room-compiler: 2.3.0-alpha02 реализация android.arch.persistence.room:runtime:1.1.1 kapt android.arch.persistence.room:compiler:1.1.1 - person Boysteuf; 24.08.2020

Хорошо, похоже, это работает:

lateinit var database: MyDatabase

@Provides
@Singleton
fun provideDatabase(@ApplicationContext context: Context): MyDatabase{
    database = Room.databaseBuilder(
        context,
        MyDatabase::class.java,
        MyDatabase.DATABASE_NAME
    )
        .fallbackToDestructiveMigration()
        .build()

    return database
}


@Provides
@Singleton
fun provideUserDao(): UserDao {
    return database.getUserDao()
}

На самом деле, мне приходится повторно использовать переменную базы данных во всех моих Дао. Пока не понимаю почему, продолжаю искать.

РЕДАКТИРОВАТЬ:

Неважно ... он работает при компиляции, но не при запуске приложения:

база данных свойств lateinit не была инициализирована

person Boysteuf    schedule 26.08.2020

Если вы используете несколько модулей, попробуйте добавить зависимости и в модуль приложения:

build.gradle (приложение)

implementation "androidx.room:room-runtime:${versions.androidx_room}"
implementation "androidx.room:room-ktx:${versions.androidx_room}"
kapt "androidx.room:room-compiler:${versions.androidx_room}"
person Alektas    schedule 30.09.2020