我向Room数据库构建器添加了一个复杂的迁移。由于这种特定的迁移需要从服务器下载一些数据,因此我在启动应用程序的主要活动之前,使用启动屏幕等待整个过程完成。
问题是,迁移似乎不会在内部独立的线程上执行,因此迁移不会自动在“ build()”方法上执行。
我还考虑过使用RoomDatabase.Callback来检测何时打开数据库,但是由于迁移过程很复杂,并且尝试从服务器下载数据,因此它可能会失败,并且应用程序可能会永远等待。
我需要触发迁移并等待其完成,并尽可能捕获迁移错误。
这是Application类上的代码:
appLoadingStatus.value = AppLoadingStatus.INITIALIZING
db= Room.databaseBuilder(this@App,Database::class.java,"app-database")
.addMigrations(Database.MIGRATION_12_13).build()
//Here I need to wait for migrations to finish in case they are executed, and catch ay possible errors
appLoadingStatus.value = AppLoadingStatus.INITIALIZED
这是迁移:
val MIGRATION_12_13: Migration = object : Migration(12, 13) {
override fun migrate(database: SupportSQLiteDatabase) {
runBlocking(Dispatchers.Main) {
val newIds =App.instance.getIdsForMigration()?:throw IllegalStateException("Unable do get data from server")
database.execSQL("ALTER TABLE Coin ADD `id` INTEGER NOT NULL")
newIds.forEach {symbolIdPair->
database.execSQL("UPDATE Coin SET id='${symbolIdPair.id}' where symbol='${symbolIdPair.symbol}'")
}
database.execSQL("ALTER TABLE Coin RENAME TO `Coin_backup`")
database.execSQL("CREATE TABLE `Coin` (`symbol` TEXT NOT NULL, `id` INTEGER NOT NULL, `name` TEXT, `imageSrc` TEXT, `rank` INTEGER NOT NULL, `max_supply` REAL NOT NULL, `quantity` REAL NOT NULL, `market` TEXT NOT NULL, `type` TEXT, `price` REAL NOT NULL, `lastUpdate` INTEGER NOT NULL, `lastVolume` REAL NOT NULL, `lastVolumeTo` REAL NOT NULL, `volumeDay` REAL NOT NULL, `volumeDayTo` REAL NOT NULL, `volume24h` REAL NOT NULL, `volume24hTo` REAL NOT NULL, `openDay` REAL NOT NULL, `highDay` REAL NOT NULL, `lowDay` REAL NOT NULL, `open24h` REAL NOT NULL, `high24h` REAL NOT NULL, `low24h` REAL NOT NULL, `change24h` REAL NOT NULL, `changePct24h` REAL NOT NULL, `changeDay` REAL NOT NULL, `changePctDay` REAL NOT NULL, `supply` REAL NOT NULL, `mktCap` REAL NOT NULL, `totalVolume24h` REAL NOT NULL, `totalVolume24hTo` REAL NOT NULL, `favourite` INTEGER NOT NULL, PRIMARY KEY(`id`))")
database.execSQL("INSERT INTO `Coin` SELECT * FROM `Coin_backup`")
}
}
}
答案 0 :(得分:0)
好吧,经过大量测试并阅读了一半的Room源代码之后,事实证明,迁移将在您首次访问内置数据库时运行。同样,在迁移过程中发生的任何错误都将在第一次调用时抛出。
如果您正在使用协程,请不要在runBlocking块上调用任何与DB相关的方法,这一点很重要,因为它可能导致房间实现中的死锁。
您可以简单地致电
db.openHelper.readableDatabase
并等待使用协同程序完成它。在这里也可以捕获错误,因此您可以检测到迁移失败的地方。
直到您知道...之前您都不知道...