Reputation: 600
I want to add a callback to the room database to populate initial data.
@Provides
@Singleton
fun provideRoom(context: Context): MyRoomDatabase {
return Room.databaseBuilder(context, MyRoomDatabase::class.java, "my_database")
.fallbackToDestructiveMigration()
.addCallback(object : RoomDatabase.Callback() {
@Override
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
}
})
.build()
}
For that i need the database instance in the callback to access DAO for inserting data. How does this work?
EDIT:
What I want to achieve:
Create initial data for the room database at the app installation
My Callback Class
:
class RoomCallback(
var myRoomDatabase : MyRoomDatabase
) : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
myRoomDatabase.basicItemDao().insertList(
listOf(
BasicItem(),
BasicItem()
)
)
}
}
How i provide the RoomDatabase
and the RoomCallback
:
@Provides
@Singleton
fun provideRoom(context: Context, roomCallback: RoomCallback): MyRoomDatabase {
return Room.databaseBuilder(context, MyRoomDatabase::class.java, "my_database")
.fallbackToDestructiveMigration()
.addCallback(roomCallback)
.build()
}
@Provides
@Singleton
fun provideRoomCallback(myRoomDatabase: MyRoomDatabase): RoomCallback {
return RoomCallback(myRoomDatabase)
}
PROBLEM:
- The RoomCallback
and RoomDatabase
instance need both the other instance.
Upvotes: 5
Views: 3906
Reputation: 1801
UPDATE: Using Kotlin Coroutine
and Dagger2
Late in the party but for future readers, it's very easy to prepopulate your database at creation time or openning time. Make sure you have already added dependency in the gradle
file for Coroutine
. First create your database like:
/**
* Main database.
*/
@Database(
entities = [
Login::class],
version = 1,
exportSchema = false
)
abstract class AppDatabase : RoomDatabase() {
abstract fun loginDao(): LoginDao
companion object {
@Volatile private var INSTANCE: AppDatabase? = null
fun getInstance(app: Application): AppDatabase = INSTANCE ?: synchronized(this) {
INSTANCE ?: buildDatabase(app).also { INSTANCE = it }
}
private fun buildDatabase(app: Application) =
Room.databaseBuilder(app,
AppDatabase::class.java,
"your database name")
.addCallback(object : Callback() {
// Pre-populate the database after onCreate has been called. If you want to prepopulate at opening time then override onOpen function instead of onCreate.
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
// Do database operations through coroutine or any background thread
val handler = CoroutineExceptionHandler { _, exception ->
println("Caught during database creation --> $exception")
}
CoroutineScope(Dispatchers.IO).launch(handler) {
prePopulateAppDatabase(getInstance(app).loginDao())
}
}
})
.build()
suspend fun prePopulateAppDatabase(loginDao: LoginDao) {
val admin = Login(0, "Administrator", "1234", 1, isActive = true, isAdmin = true, isLogged = false)
loginDao.insertLoginData(admin)
}
}
}
Then you can provide singleton instance by placing below code to your dagger AppModule
or in a separate database module as you wish.
@Singleton
@Provides
fun provideDb(app: Application): AppDatabase {
return AppDatabase.getInstance(app)
}
@Singleton
@Provides
fun provideLoginDao(db: AppDatabase): LoginDao {
return db.loginDao()
}
that's it, you are done. Inject anywhere your singleton database object like:
@Inject lateinit var loginDao: LoginDao
then use it.
Upvotes: 9
Reputation: 5053
Setup a database first
@Database(
entities = [User::class],
version = VERSION_CODE
)
abstract class DatabaseManager : RoomDatabase() {
abstract fun userDao(): UserDao
}
Now create a DatabaseModule
@Module
class DatabaseModule {
@Singleton
@Provides
fun provideRoomDatabase(@ApplicationContext context: Context): RoomDatabase {
return Room.databaseBuilder(context, RoomDatabase::class.java, "dbName")
.setJournalMode(JournalMode.TRUNCATE)
.build()
}
}
You can create a separate module or add a method in DatabaseModule
it self providing dao object. Say for example I have a UserDao
then
@Module
class UserModule {
@Singleton
@Provides
fun provideDao(database: DatabaseManager): UserDao {
return database.userDao()
}
}
Upvotes: 5