I am trying to prepoluate Room database with data using RoomDatabase.Callback() method and also had success in doing so . Later I tried to work the same with Hilt , but can't figure out how to add the callback while providing the database in hilt module .
This is the DatabaseModule :
@Module
@InstallIn(ApplicationComponent::class)
object DatabaseModule {
@Singleton
@Provides
fun provideDatabase(
@ApplicationContext context: Context
): PersonDatabase {
return Room.databaseBuilder(
context,
PersonDatabase::class.java,
"person_database"
).build()
}
@Singleton
@Provides
fun provideDao(database: PersonDatabase) = database.personDao()
}
This is the Callback class :
class PersonCallback @Inject constructor(
private val dao: PersonDao
) : RoomDatabase.Callback() {
private val applicationScope = CoroutineScope(SupervisorJob())
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
applicationScope.launch(Dispatchers.IO) {
populateDatabase()
}
}
private suspend fun populateDatabase() {
val person = Person("FirstName", "LastName", 20)
dao.insertData(person)
}
}
What I have tried is using the database and providing the dao like this , but it stucks at a loop and the app crashes out . The error in short says , that the following manner is recursive and hence not permittable
@Singleton
@Provides
fun provideDatabase(
@ApplicationContext context: Context
): PersonDatabase {
return Room.databaseBuilder(
context,
PersonDatabase::class.java,
"person_database"
).addCallback(
PersonCallback(provideDatabase(context).personDao())
).build()
}
Then , I followed an SO post and tried to replicate it , which is :
Pre-populating Room database with Hilt without creating an extra instance of the database
Following the above , the application crashed again , providing a huge error which referenced to autogenerated class and had nothing much to it to make it more meaningful
Another Method which I tried was to pass dao as an parameter , but it again crashed with an error saying it leads to a dependency cycle since I also have passed the dao to the Repository as a constructor parameter.
@Singleton
@Provides
fun provideDatabase(
@ApplicationContext context: Context,
personDao: PersonDao
): PersonDatabase {
return Room.databaseBuilder(
context,
PersonDatabase::class.java,
"person_database"
).addCallback(
PersonCallback(personDao)
).build()
}
After all this tries , I am not able to figure out how should I pass dao to the callback class and make it work . I request to suggest some ways to make this happen or any alternatives will also be appreciated .
According link you add in your question you find solution just edit first method provide PersonDatabase
@Singleton
@Provides
fun provideDatabase(
@ApplicationContext context: Context,
provider: Provider<PersonDao>
): PersonDatabase {
return Room.databaseBuilder(
context,
PersonDatabase::class.java,
"person_database"
).addCallback(
PersonCallback(provider)
).build()
}
Then your callback Class take provider for PersonDao jus edit for your class
class PersonCallback (
private val provider: Provider<PersonDao>
) : RoomDatabase.Callback() {
private val applicationScope = CoroutineScope(SupervisorJob())
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
applicationScope.launch(Dispatchers.IO) {
populateDatabase()
}
}
private suspend fun populateDatabase() {
val person = Person("FirstName", "LastName", 20)
provider.get().insertData(person)
}
}
I try this code work fine with me