Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
418 views
in Technique[技术] by (71.8m points)

java - Room Database force OnCreate callback

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
    }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...