In this post I will show the method I used to add a predetermined set of values to prefill Android Room Database at time of creation.
The project I was working on needed a list of strings for the user to choose from. The list needed to also be editable. The best option I chose was Room database. The issue was I needed to prefill Android Room database with values when it gets created so the user already has options to choose from. This would give the user a better experience.
I needed to configure this need inside the method used to create the instance of the database. When you access the database object, the method checks if the database has already been created. If it hasn't, then it will create it. We will need to add the predetermined values inside this part of the method.
Process
Inside the method where the instance is returned, we need to add a callback to the database builder.
This callback is implemented between the databaseBuilder() function and the final build() function.
val instance = Room.databaseBuilder(
context.applicationContext,
CategoryDatabase::class.java,
"category_database"
)
//start ----this is where the prefill happens
.addCallback(object: RoomDatabase.Callback(){
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
db.beginTransaction()
//process insert statements here
db.setTransactionSuccessful()
db.endTransaction()
}
})
//end -------
.build()
This will allow us to override the onCreate method. Inside the onCreate method we will access the list needed to populate in the database and set them in ContentValues. The ContentValues are used to in a database insert statement.
Below is the method I used to implement it.
Code
I put the values I wanted in an object class exposing a list. This was the fastest way to add a list that could be easily accessible from the database object.
object CategoryTypes {
val list: List<String> = listOf("Grocery", "Home", "Family", "Honey Do", "Work", "Bucket List", "Movies", "TV Shows", "Books", "Workout")
}
Then inside the database helper that creates the Room database and provides the instance of it, I added a callback for the onCreate method.
@Database(
entities = [CategoryTable::class],
version = 1,
exportSchema = true
)
abstract class CategoryDatabase : RoomDatabase(){
abstract fun categoryDao(): CategoryDao
companion object {
// Singleton prevents multiple instances of database opening at the
// same time.
@Volatile
private var INSTANCE: CategoryDatabase? = null
fun getDatabase(context: Context): CategoryDatabase {
// if the INSTANCE is not null, then return it,
// if it is, then create the database
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
CategoryDatabase::class.java,
"category_database"
)
//start ----this is where the prefill happens
.addCallback(object: RoomDatabase.Callback(){
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
db.beginTransaction()
val values = ContentValues()
val categoryTypes = CategoryTypes.list
categoryTypes.forEach {
values.put("category", it)
db.insert("categories", SQLiteDatabase.CONFLICT_ABORT, values)
}
db.setTransactionSuccessful()
db.endTransaction()
}
})
//end -------
.build()
INSTANCE = instance
// return instance
instance
}
}
}
}
Hope this is useful.