我在项目中使用Android Room,遇到了以下问题:
RoomDatabase.Callback#onCreate
)是否可以保证始终被调用?如果是这样,在此回调中运行插入查询以预填充数据库是否安全(如果不执行查询,则每次用户打开该应用都会使该应用崩溃)?我之所以问这个原因是因为,目前,我正在我的应用程序上执行此操作。我利用该回调函数来预填充数据库,但是我看到某些用户反复发生崩溃。当应用尝试获取这些预先填充的数据之一,但不存在这些崩溃时(返回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!!
}
答案 0 :(得分:0)
是Room的数据库创建回调(RoomDatabase.Callback#onCreate) 保证总是被叫?
根据文档,在创建所有表之后首次创建数据库时调用它。
未调用onCreate()
(虽然您可能希望如此)的一种情况是找不到向当前版本的迁移,并且在数据库构建器上设置了fallbackToDestructiveMigration()
。在这种情况下,无需调用onCreate()
即可重新创建数据库。我不确定这是否是设计使然,但目前是这样。
如果是这样,在此回调中运行插入查询是否安全? 预填充数据库-查询,如果不执行,将使 用户每次打开应用程序都会崩溃吗?
在这里填充数据库是安全的,假设在您期望它被调用的时候就被调用,据我了解,这仅是在第一次创建数据库时。
因此,如果Room在某些版本中找不到迁移项目,那么如果您的应用程序未设计为处理丢失的数据,则可能会导致崩溃。
我对Room如何处理迁移的观察(自v2.2.0-alpha01起):
根据addMigrations()
的文档:
如果当前版本和最新版本之间缺少迁移项目 版本,Room将清除数据库并重新创建。.
可能是这种情况,但它还会引发以下IllegalStateException:
需要从1迁移到2,但未找到。请提供 通过必要的迁移路径 RoomDatabase.Builder.addMigration(Migration ...)或允许 通过以下方式之一进行破坏性迁移 RoomDatabase.Builder.fallbackToDestructiveMigration *方法。
如果您将fallbackToDestructiveMigration()
添加到数据库构建器中(如异常所示),则确实会重新创建(或至少清除了)数据库,但是不会调用onCreate()
,因此如果您的填充代码在在那里,您最终将没有应用程序的数据。
因此,我相信onCreate()
是填充数据库的可行选择,只要您承诺向Room提供它可能需要的所有必要迁移。