【问题标题】:Detect when Room has finished running migrations检测 Room 何时完成运行迁移
【发布时间】:2019-03-06 21:32:50
【问题描述】:

我的 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`")
        }
    }
}

【问题讨论】:

    标签: android kotlin android-room kotlin-coroutines


    【解决方案1】:

    好吧,经过大量测试并阅读了一半 Room 源代码后,事实证明迁移将在您第一次访问构建的数据库时运行。此外,迁移期间发生的任何错误都将在第一次调用时抛出。

    如果您使用协程,在 runBlocking 块上调用任何与 DB 相关的方法时要小心,因为它可能导致房间实现中的死锁。

    你可以直接调用

    db.openHelper.readableDatabase
    

    然后等待它完成。错误也可以在此处捕获,因此您可以检测迁移失败的位置。

    你不知道,直到你知道......

    【讨论】:

    • 您能否详细说明您的观点“并等待使用协程完成”?
    • 答案已编辑。您实际上根本不需要使用协程。在 getReadableDatabase() 调用之后,您可以确定迁移步骤已完成。
    猜你喜欢
    • 2021-09-12
    • 2018-07-10
    • 1970-01-01
    • 2011-11-12
    • 2017-08-04
    • 2022-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多