房间数据库强制 OnCreate 回调

Room Database force OnCreate callback

我正在使用需要预填充数据的 RoomDatabase 开发应用程序;我已经设法通过添加 onCreate() 回调来做到这一点,但只有在第一次访问数据库时才会调用它(比如调用一个 Daos 函数)。

有什么方法可以在不进行任何读取或写入操作的情况下强制创建数据库?

那是我的代码,MyDatabase.get()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
    }

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

不,抱歉。

不过,没有什么可以阻止您在调用 Room 之前将预先填充的数据库复制到位。您需要确保预填充的数据库中包含 Room 的元数据(例如,通过使用 Room 本身创建该数据库)。

我花了一段时间才明白为什么在数据库构建器上调用 .build() 后 Room 数据库没有填充初始数据。

对我来说,只有在真正的 read/write 操作中才会触发迁移和回调,这确实违反直觉。实际上,问题是由 Room 使用 class RoomOpenHelper 的原因引起的,如文档中所述:

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

因此,配置和所有回调存储在 RoomOpenHelper class 的实例中,而 Sqlite 的 SQLiteOpenHelper 实际执行数据库迁移,而不是创建(惰性 class 载入 Java).

要克服此行为,应执行任何导致 getWritableDatabase() 的操作。我最终采用了以下方法:

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

之后将创建数据库并填充初始数据。

Room version 2.2.0 (October 2019) 引入了数据库预填充的内置方法:

  1. 来自您应该放在 assets/ 目录中的预先打包的数据库文件 (*.db)。
  2. 来自预先打包的数据库文件 (*.db),您应该将其放置在 assets/ 目录以外的某个地方。

有关详细信息,您可以阅读 official documentation

要获得答案 - 如何准备预打包数据库,您可以阅读