Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I'm developing an application with RoomDatabase that needs to pre-populate its data; I already managed to do it by adding the onCreate() callback, but it gets called only when accessing the database the first time (like calling one of the Daos functions).

Is there any way to force the database creation without doing any read or write operation?

That's my code, MyDatabase.get() is called in App.onCreate()

@Database(entities = {Entity1.class, Entity2.class}, version = 1, exportSchema = true)
public abstract class MyDatabase extends RoomDatabase {
    private static MyDatabase sInstance;
    public synchronized static TaxCodeDatabase get(Context context) {
        if (sInstance == null) {
            sInstance = buildDatabase(context);
        return sInstance;
    private static MyCodeDatabase buildDatabase(final Context context) {
        return Room.databaseBuilder(context,
                MyCodeDatabase.class,
                "my-database")
                .addCallback(new Callback() {
                    @Override
                    public void onCreate(@NonNull SupportSQLiteDatabase db) {
                        super.onCreate(db);
                        sInstance.preFillData(context);
                .build();
    public abstract Entity1Dao entity2Dao();
    public abstract Entity2Dao entity1Dao();
     * Populates the database with a series of initial data
     * @param aContext
    public void prePopulateData(Context aContext) {
        //Populate database here
                Why not create a subclass of Application and call your MyDatabase singleton in that part? Take note onCreate is only called once not unless you delete your database.
– Enzokie
                Jan 16, 2018 at 12:17

It's took me a while to understand why a Room database is not populated with initial data after invoking .build() on a database builder.

As for me, it's really counter-intuitive that migrations and callbacks are triggered only on real read/write operation. Actually the issue caused by the reason that Room use class RoomOpenHelper which, as mentioned in documentation:

An open helper that holds a reference to the configuration until the database is opened.

As the result, configuration and all callbacks stored in the instance of RoomOpenHelper class while Sqlite's SQLiteOpenHelper, which actually performs database migrations, not created (lazy class loading in Java).

To overcome this behavior, any operation which cause getWritableDatabase() should be performed. I ended up with the following approach:

RoomDatabase db = Room.databaseBuilder(context,
            .build();
  // and then
db.beginTransaction()
db.endTransaction()
  // or query a dummy select statement
db.query("select 1", null)
return db

After that the database will be created and populated with initial data.

how to do that with populated database in asset force room to delete previous db and then recreate it from asset bcz fallbackToDestructiveMigration do that but with empty db i want to recreate it and then copy database tables from asset thanks ! – Ayoub Benzahia Dec 31, 2020 at 14:07

Is there any way to force the database creation without doing any read or write operation?

No, sorry.

There is nothing stopping you from copying the pre-populated database into position before invoking Room, though. You would need to ensure that the pre-populated database has Room's metadata in it (e.g., by creating that database using Room itself).

@CommonsWare Wouldn't his code with super.onCreate(db); sInstance.preFillData(context); trigger recursive calls of onCreate()? The only ways to avoid this is either to: 1)call sInstance.preFillData(context) from separate thread or (2)to use raw SQL queries on db object like in your book (but we lose type safety of Room). Is it really so or you have better proposal for pre-populating – Ewoks Jun 19, 2018 at 9:08 @Ewoks: A separate thread would be seriously dangerous here. Instead, you could do preFillData() outside the callback, but inside buildDatabase(), where preFillData() also checks for whether the data has been loaded previously or not. – CommonsWare Jun 19, 2018 at 10:48

Room version 2.2.0 (October 2019) introduced built-in methods for database's pre-population:

  • From the prepackaged database file (*.db) that you should place inside assets/ directory.
  • From the prepackaged database file (*.db) that you should place somewhere except assets/ directory.
  • For more details you can read official documentation.

    For getting answer - how to prepare prepackaged database you can read this article in SO.

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.