Reputation: 253
So I'm trying to use Room on a personnal project. I have implemented my entities, dao and my roomdatabase extended application class :
@Database(
version = 1,
entities = [
UserDBEntity::class
]
)
abstract class MyDatabase: RoomDatabase() {
companion object {
const val DATABASE_NAME = "MyDb"
}
abstract fun getUserDao(): UserDao
}
However, I'm also trying to use Hilt DI with it, so, I created a module like that :
@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()
}
}
Everything seems good to me. However, when I try to compile, I've got this error message :
class file for androidx.room.RoomDatabase not found
Any idea of what I missed ?
If it can help you, I tried to change my build.gradle from this :
implementation "androidx.room:room-runtime:2.3.0-alpha02"
To this :
api "androidx.room:room-runtime:2.3.0-alpha02"
And with that, it compiles succefully, but I don't think it's a good practice, looking the tutorials I found.
Don't hesitate if you need more details on my code.
Thank you for your answers :)
EDIT :
My build.gradle for Room :
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"
With this also :
apply plugin: 'kotlin-kapt'
EDIT 2 :
I think I found what is the cause of the problem. I called my DAO method in a class like that :
@Singleton
class DBManagerImpl @Inject constructor(
private val userDao: UserDao
) : DBManager {
override fun insertUser(userDBEntity: UserDBEntity) {
userDao.insertUser(userDBEntity)
}
}
It seems the problem is in the userDao injection cause if I comment the "private val userDao: UserDao" line, I don't have the error anymore. So I think my problem comes from my way to inject the dao object.
Upvotes: 4
Views: 3690
Reputation: 27
Try "api "androidx.room:room-runtime:2.3.0-alpha02"" instead of "implementation "androidx.room:room-runtime:2.3.0-alpha02"". I don't know why, but it worked for me
Upvotes: 1
Reputation: 3625
I faced that problem because I was adding dependencies of room to the core module so for those who using modular architecture be sure you added dependencies of room to the app module also
Upvotes: 5
Reputation: 29458
I had the same problem. It can be fixed with Dagger, but not with Hilt. At least, for now. It seems that for now best solution is using api
instead of implementation
. If you strongly want to avoid it, you can use something like this:
@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()
}
}
But, as I've said - maybe for now it's better to leave api
in gradle
Upvotes: 1
Reputation: 656
If you are using multiple modules, try adding dependencies to the App module too:
build.gradle (app)
implementation "androidx.room:room-runtime:${versions.androidx_room}"
implementation "androidx.room:room-ktx:${versions.androidx_room}"
kapt "androidx.room:room-compiler:${versions.androidx_room}"
Upvotes: 1
Reputation: 4732
Since you did not provide how you created your dao object, I've written my own and provide it in this answer. This should work:
@Database(version = 1,entities = [UserDBEntity::class])
abstract class MyDataBase() : RoomDatabase() {
abstract fun myDao(): UserDao
companion object {
val DATABASE_NAME = "my_db"
}
}
@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()
}
Upvotes: 1
Reputation: 253
OK, so, it seems that this is working :
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()
}
Actually, I have to reuse the database variable on all my dao providing. I don't yet understand why, I keep searching.
EDIT :
Nevermind ... it works on compile but not when I launch the app :
lateinit property database has not been initialized
Upvotes: 0
Reputation: 2729
Do you have 2 lines in app gradle file:
apply plugin: 'kotlin-kapt'
kapt "androidx.room:room-compiler:2.2.5"
Upvotes: 0