Jeśli chcesz, aby aplikacja uruchamiała się z bazą danych, która jest już wypełniona określonym zestawem danych, możesz wstępnie wypełnić bazę danych. W Room możesz używać interfejsów API do wstępnego wypełniania bazy danych podczas inicjowania treścią z preinstalowanego pliku bazy danych w systemie plików urządzenia.
Wstępne wypełnianie z komponentu z linkiem do aplikacji
Aby wstępnie wypełnić bazę danych Room z preinstalowanego pliku bazy danych, który znajduje się
w dowolnym miejscu w katalogu assets/ aplikacji, przed wywołaniem funkcji build wywołaj funkcję createFromAsset z obiektu RoomDatabase.Builder:
Room.databaseBuilder<AppDatabase>(appContext, "sample.db") .createFromAsset("database/myapp.db") .build()
Funkcja createFromAsset przyjmuje argument ciągu znaków, który zawiera ścieżkę względną od katalogu assets/ do preinstalowanego pliku bazy danych.
Wstępne wypełnianie z systemu plików
Aby wstępnie wypełnić bazę danych Room z preinstalowanego pliku bazy danych, który znajduje się
w dowolnym miejscu w systemie plików urządzenia z wyjątkiem katalogu assets/ aplikacji,
przed wywołaniem funkcji build wywołaj funkcję createFromFile z obiektu RoomDatabase.Builder:
Room.databaseBuilder<AppDatabase>(appContext, "sample.db") .createFromFile(File("mypath")) .build()
Funkcja createFromFile przyjmuje argument File dla
preinstalowanego pliku bazy danych. Room tworzy kopię wyznaczonego pliku, zamiast otwierać go bezpośrednio, więc upewnij się, że Twoja aplikacja ma uprawnienia do odczytu tego pliku.
Obsługa migracji obejmujących preinstalowane bazy danych
Preinstalowane pliki bazy danych mogą też zmieniać sposób, w jaki baza danych Room obsługuje migracje rezerwowe. Zwykle, gdy włączone są migracje destrukcyjne i Room musi przeprowadzić migrację bez ścieżki migracji, Room usuwa wszystkie tabele w bazie danych i tworzy pustą bazę danych z określonym schematem dla wersji docelowej. Jeśli jednak dołączysz preinstalowany plik bazy danych o tym samym numerze co wersja docelowa, Room po przeprowadzeniu migracji destrukcyjnej wypełni nowo utworzoną bazę danych zawartością preinstalowanego pliku bazy danych.
Więcej informacji o migracjach baz danych Room znajdziesz w artykule Migracja bazy danych Room.
W kolejnych sekcjach znajdziesz kilka przykładów działania tej funkcji w praktyce.
Przykład: migracja rezerwowa z preinstalowaną bazą danych
Załóżmy, że:
- Twoja aplikacja definiuje bazę danych Room w wersji 3.
- Instancja bazy danych, która jest już zainstalowana na urządzeniu, ma wersję 2.
- Istnieje preinstalowany plik bazy danych w wersji 3.
- Nie ma zaimplementowanej ścieżki migracji z wersji 2 do wersji 3.
- Migracje destrukcyjne są włączone.
// 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() }
W tej sytuacji dzieje się tak:
- Ponieważ baza danych zdefiniowana w aplikacji ma wersję 3, a instancja bazy danych już zainstalowana na urządzeniu ma wersję 2, konieczna jest migracja.
- Ponieważ nie ma zaimplementowanego planu migracji z wersji 2 do wersji 3, migracja jest migracją rezerwową.
- Ponieważ wywołujesz funkcję konstruktora
fallbackToDestructiveMigrationbuilder, migracja rezerwowa jest destrukcyjna. Room usuwa instancję bazy danych zainstalowaną na urządzeniu. - Ponieważ istnieje preinstalowany plik bazy danych w wersji 3, Room ponownie tworzy bazę danych i wypełnia ją zawartością preinstalowanego pliku bazy danych. Jeśli preinstalowany plik bazy danych ma wersję 2, Room stwierdza, że nie pasuje do wersji docelowej, i nie używa go do migracji rezerwowej.
Przykład: zaimplementowana migracja z preinstalowaną bazą danych
Załóżmy, że Twoja aplikacja implementuje ścieżkę migracji z wersji 2 do wersji 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() }
W tej sytuacji dzieje się tak:
- Ponieważ baza danych zdefiniowana w aplikacji ma wersję 3, a baza danych już zainstalowana na urządzeniu ma wersję 2, konieczna jest migracja.
- Ponieważ istnieje zaimplementowana ścieżka migracji z wersji 2 do wersji 3,
Room uruchamia zdefiniowaną funkcję
migrate, aby zaktualizować instancję bazy danych na urządzeniu do wersji 3, zachowując dane, które są już w bazie danych. Room nie używa preinstalowanego pliku bazy danych, ponieważ używa go tylko w przypadku migracji rezerwowej.
Przykład: migracja wieloetapowa z preinstalowaną bazą danych
Preinstalowane pliki bazy danych mogą też wpływać na migracje, które składają się z kilku etapów. Rozważmy ten przypadek:
- Twoja aplikacja definiuje bazę danych Room w wersji 4.
- Instancja bazy danych, która jest już zainstalowana na urządzeniu, ma wersję 2.
- Istnieje preinstalowany plik bazy danych w wersji 3.
- Istnieje zaimplementowana ścieżka migracji z wersji 3 do wersji 4, ale nie z wersji 2 do wersji 3.
- Migracje destrukcyjne są włączone.
// 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() }
W tej sytuacji dzieje się tak:
- Ponieważ baza danych zdefiniowana w aplikacji ma wersję 4, a instancja bazy danych już zainstalowana na urządzeniu ma wersję 2, konieczna jest migracja.
- Ponieważ nie ma zaimplementowanej ścieżki migracji z wersji 2 do wersji 3, migracja jest migracją rezerwową.
- Ponieważ wywołujesz funkcję konstruktora
fallbackToDestructiveMigrationbuilder, migracja rezerwowa jest destrukcyjna. Room usuwa instancję bazy danych na urządzeniu. - Ponieważ istnieje preinstalowany plik bazy danych w wersji 3, Room ponownie tworzy bazę danych i wypełnia ją zawartością preinstalowanego pliku bazy danych.
- Baza danych zainstalowana na urządzeniu ma teraz wersję 3. Ponieważ jest ona nadal starsza niż wersja zdefiniowana w aplikacji, konieczna jest kolejna migracja.
- Ponieważ istnieje zaimplementowana ścieżka migracji z wersji 3 do wersji 4,
Room uruchamia zdefiniowaną funkcję
migrate, aby zaktualizować instancję bazy danych na urządzeniu do wersji 4, zachowując dane, które zostały skopiowane z preinstalowanego pliku bazy danych w wersji 3.