Если вы хотите, чтобы ваше приложение запускалось с базой данных, уже загруженной определенным набором данных, вы можете предварительно заполнить ее. В Room вы можете использовать API для предварительного заполнения базы данных при инициализации содержимым из предварительно упакованного файла базы данных в файловой системе устройства.
Предварительное заполнение из ресурсов приложения
Чтобы предварительно заполнить базу данных Room из предварительно подготовленного файла базы данных, расположенного в любом месте каталога assets/ вашего приложения, вызовите функцию createFromAsset из объекта RoomDatabase.Builder перед вызовом build :
Room.databaseBuilder<AppDatabase>(appContext, "sample.db") .createFromAsset("database/myapp.db") .build()
Функция createFromAsset принимает строковый аргумент, содержащий относительный путь от каталога assets/ к предварительно упакованному файлу базы данных.
Предварительное заполнение из файловой системы
Чтобы предварительно заполнить базу данных Room из предварительно упакованного файла базы данных, расположенного в любом месте файловой системы устройства, кроме каталога assets/ вашего приложения, вызовите функцию createFromFile из объекта RoomDatabase.Builder перед вызовом build :
Room.databaseBuilder<AppDatabase>(appContext, "sample.db") .createFromFile(File("mypath")) .build()
Функция createFromFile принимает в качестве аргумента File базы данных, предварительно подготовленный для этой функции. Room создает копию указанного файла, а не открывает его напрямую, поэтому убедитесь, что ваше приложение имеет права на чтение этого файла.
Обработка миграций, включающих предварительно подготовленные базы данных.
Предварительно упакованные файлы базы данных также могут изменить способ обработки резервных миграций в вашей базе данных Room. Обычно, когда включены деструктивные миграции и Room необходимо выполнить миграцию без указания пути миграции, Room удаляет все таблицы в базе данных и создает пустую базу данных с указанной схемой для целевой версии. Однако, если вы включите предварительно упакованный файл базы данных с тем же номером, что и целевая версия, Room заполнит вновь созданную базу данных содержимым этого предварительно упакованного файла базы данных после выполнения деструктивной миграции.
Для получения дополнительной информации о миграции базы данных Room см. раздел «Миграция базы данных Room» .
В следующих разделах представлены несколько примеров того, как это работает на практике.
Пример: Резервная миграция с использованием готовой базы данных.
Предположим следующее:
- В вашем приложении используется база данных Room версии 3.
- Установленная на устройстве база данных имеет версию 2.
- Имеется предварительно настроенный файл базы данных версии 3.
- В настоящее время отсутствует реализованный путь миграции с версии 2 на версию 3.
- Деструктивная миграция включена.
// Database class definition declaring version 3. @Database(entities = [SampleEntity::class], version = 3) abstract class FallbackAppDatabase : RoomDatabase() { // ... } fun createFallbackDb(appContext: Context) { Room.databaseBuilder<FallbackAppDatabase>(appContext, "sample.db") .createFromAsset("database/myapp.db") .fallbackToDestructiveMigration() .build() }
Вот что происходит в этой ситуации:
- Поскольку база данных, определенная в вашем приложении, имеет версию 3, а экземпляр базы данных, уже установленный на устройстве, имеет версию 2, необходима миграция.
- Поскольку план миграции с версии 2 на версию 3 не реализован, используется резервный вариант миграции.
- Поскольку вы вызываете функцию построения
fallbackToDestructiveMigration, резервная миграция является деструктивной. Room удаляет экземпляр базы данных, установленный на устройстве. - Поскольку существует предварительно подготовленный файл базы данных версии 3, Room пересоздает базу данных и заполняет ее содержимым этого предварительно подготовленного файла. Если ваш предварительно подготовленный файл базы данных версии 2, Room определяет, что он не соответствует целевой версии, и не использует его для резервной миграции.
Пример: Реализована миграция с использованием готовой базы данных.
Предположим, что ваше приложение реализует путь миграции со версии 2 на версию 3:
// Database class definition declaring version 3. @Database(entities = [SampleEntity::class], version = 3) abstract class ImplementedAppDatabase : RoomDatabase() { // ... } // Migration path definition from version 2 to version 3. val MIGRATION_2_3 = object : Migration(2, 3) { override suspend fun migrate(connection: SQLiteConnection) { // ... } } fun createImplementedDb(appContext: Context) { Room.databaseBuilder<ImplementedAppDatabase>(appContext, "sample.db") .createFromAsset("database/myapp.db") .addMigrations(MIGRATION_2_3) .build() }
Вот что происходит в этой ситуации:
- Поскольку база данных, определенная в вашем приложении, имеет версию 3, а база данных, уже установленная на устройстве, — версию 2, необходима миграция.
- Поскольку существует реализованный путь миграции с версии 2 на версию 3, Room запускает определенную функцию
migrateдля обновления экземпляра базы данных на устройстве до версии 3, сохраняя при этом данные, уже имеющиеся в базе данных. Room не использует предварительно подготовленный файл базы данных, поскольку Room использует предварительно подготовленные файлы базы данных только в случае резервной миграции.
Пример: Многоэтапная миграция с использованием готовой базы данных.
Предварительно подготовленные файлы базы данных также могут влиять на миграции, состоящие из нескольких этапов. Рассмотрим следующий случай:
- В вашем приложении используется база данных Room версии 4.
- Установленная на устройстве база данных имеет версию 2.
- Имеется предварительно настроенный файл базы данных версии 3.
- Реализован путь миграции с версии 3 на версию 4, но не с версии 2 на версию 3.
- Деструктивная миграция включена.
// Database class definition declaring version 4. @Database(entities = [SampleEntity::class], version = 4) abstract class MultiStepAppDatabase : RoomDatabase() { // ... } val MIGRATION_3_4 = object : Migration(3, 4) { override suspend fun migrate(connection: SQLiteConnection) { // ... } } fun createMultiStepDb(appContext: Context) { Room.databaseBuilder<MultiStepAppDatabase>(appContext, "sample.db") .createFromAsset("database/myapp.db") .addMigrations(MIGRATION_3_4) .fallbackToDestructiveMigration() .build() }
Вот что происходит в этой ситуации:
- Поскольку база данных, определенная в вашем приложении, имеет версию 4, а экземпляр базы данных, уже установленный на устройстве, имеет версию 2, необходима миграция.
- Поскольку реализованного пути миграции со версии 2 на версию 3 нет, выполняется резервная миграция.
- Поскольку вы вызываете функцию построения
fallbackToDestructiveMigration, резервная миграция является деструктивной. Room удаляет экземпляр базы данных на устройстве. - Поскольку существует предварительно подготовленный файл базы данных версии 3, Room пересоздает базу данных и заполняет ее содержимым этого предварительно подготовленного файла базы данных.
- Установленная на устройстве база данных теперь имеет версию 3. Поскольку она все еще ниже версии, определенной в вашем приложении, необходима еще одна миграция.
- Поскольку существует реализованный путь миграции с версии 3 на версию 4, Room запускает определенную функцию
migrateдля обновления экземпляра базы данных на устройстве до версии 4, сохраняя при этом данные, скопированные из предварительно упакованного файла базы данных версии 3.