Android 房间数据库创建 - 回调

Android Room Database Creation - Callback

我在我的项目中使用 Android Room,我遇到了以下问题:

我问这个问题的原因是,目前,我正在我的应用程序上这样做。我正在利用该回调预填充我的数据库,但我看到一些用户反复发生崩溃。当应用程序尝试获取这些预填充数据之一,但它们不存在(返回 0 行)时,就会发生这些崩溃。


fun getInstance(context: Context): MyDatabaseClass {
    if (isDeletingDatabase) throw DeletingDatabaseException()
    if (instance == null) {
        instance = Room
                .databaseBuilder(context, MyDatabaseClass::class.java, MyDatabaseClass.DB_NAME)
                .addCallback(object : RoomDatabase.Callback() {
                    override fun onCreate(db: SupportSQLiteDatabase) {
                        onDbCreated(db)
                    }
                })
                .addMigrations(
                        Migration_1_2,
                        Migration_2_3
                )
                .build()
    }
    return instance!!
}

Is Room's database creation callback (RoomDatabase.Callback#onCreate) guaranteed to always be called?

根据文档,在创建所有表后首次创建数据库时调用它。

未调用 onCreate() 的一种情况(尽管您可能期望它会调用)是未找到到当前版本的迁移并且在数据库构建器上设置了 fallbackToDestructiveMigration()。在这种情况下,数据库会在不调用 onCreate() 的情况下重新创建。我不确定这是否是设计使然,但目前确实如此。

If so, is it safe to run insert queries in this callback to prepopulate the database - queries which if not executed, will make the app crash everytime the user opens it?

在这里填充数据库是安全的,假设它在您期望的时候被调用,根据我的理解,这只是在第一次创建数据库时。

因此,如果 Room 找不到某些版本的迁移项,如果您的应用未设计为处理丢失的数据,则可能会发生崩溃。


我对 Room 如何处理迁移的观察(截至 v2.2.0-alpha01):

根据 addMigrations() 的文档:

If a migration item is missing between current version and the latest version, Room will clear the database and recreate..

可能是这样,但它也会抛出以下 IllegalStateException:

A migration from 1 to 2 was required but not found. Please provide the necessary Migration path via RoomDatabase.Builder.addMigration(Migration ...) or allow for destructive migrations via one of the RoomDatabase.Builder.fallbackToDestructiveMigration* methods.

如果您将 fallbackToDestructiveMigration() 添加到您的数据库构建器,如异常所示,数据库会重新创建(或至少被擦除),但不会调用 onCreate(),因此如果您的人口代码在那里,你最终将没有你的应用程序的数据。

出于这个原因,我相信 onCreate() 是填充数据库的可行选择,只要您承诺为 Room 提供它可能需要的所有必要迁移。