Если вы хотите, чтобы приложение запускалось с базой данных, в которую уже загружен определенный набор данных, вы можете предварительно заполнить ее. В 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 версии 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 версии 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.