Определить, когда Room завершил выполнение миграций - PullRequest
1 голос
/ 07 марта 2019

Мне добавили сложную миграцию в мой построитель базы данных Room. Поскольку для этой конкретной миграции требуется загрузка некоторых данных с сервера, я использую заставку, чтобы дождаться завершения всего процесса, прежде чем открывать основную деятельность приложения.

Проблема заключается в том, что миграции не выполняются автоматически в методе "build ()", так как кажется, что они выполняются внутри отдельного потока.

Я также подумал об использовании RoomDatabase.Callback для определения того, когда база данных открыта, но поскольку миграция является сложной и пытается загрузить данные с сервера, она может завершиться неудачно, и приложение может оставаться в ожидании вечно.

Мне нужно запустить миграцию и дождаться ее завершения и, если возможно, перехватить ошибки миграции.

Это код класса приложения:

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

1 Ответ

0 голосов
/ 08 марта 2019

Что ж, после тщательного тестирования и чтения половины исходного кода Room, оказывается, что миграции будут выполняться при первом обращении к встроенной базе данных. Также любые ошибки, произошедшие во время миграции, будут выданы при первом вызове.

Важно, если вы используете сопрограммы, а не вызывать какие-либо методы, связанные с БД, в блоке runBlocking, так как это может вызвать тупик в реализации комнаты.

Вы можете просто позвонить

db.openHelper.readableDatabase

И дождитесь его завершения, используя сопрограммы. Здесь также можно отследить ошибки, чтобы вы могли определить, где происходит сбой миграции.

Ты не узнаешь, пока не узнаешь ...

...